HAL 제어 평면(릴리스·서버·Agent·작업·모듈 배포·운영자 계정·긴급 복구·재해복구·공개 상태), Node Agent, 배포 스크립트·유닛·nginx 템플릿, 릴리스 도구, 포털 HAL 클라이언트 (§28·§29·§32~§34)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
zzabisagent-lab
2026-10-26 11:58:15 +00:00
co-authored by Claude Fable 5.1
parent 403d0fb845
commit 6b5a014041
49 changed files with 2584 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
/** hal/cidr.mjs — IP 허용 목록(CIDR) 검사(§25 운영자 콘솔 네트워크 제한). IPv4·IPv6·::ffff: 로 감싼 IPv4 를 다룬다. */
import { isIP } from 'node:net';
function toBytes(ip) {
let s = String(ip || '').trim(); if (s.startsWith('::ffff:') && isIP(s.slice(7)) === 4) s = s.slice(7);
if (isIP(s) === 4) return { v: 4, b: s.split('.').map(Number) };
if (isIP(s) !== 6) return null;
const [head, tail] = s.split('::'); const h = head ? head.split(':') : []; const t = tail ? tail.split(':') : []; const parts = [...h, ...Array(8 - h.length - t.length).fill('0'), ...t];
const b = []; for (const p of parts) { const n = parseInt(p || '0', 16); b.push(n >> 8, n & 255); } return { v: 6, b };
}
/** ip 가 cidr 목록 중 하나에 속하면 true. 목록이 비면 false(허용 네트워크 없음). */
export function ipAllowed(ip, cidrs) {
const a = toBytes(ip); if (!a) return false;
for (const c of cidrs || []) {
const [net, lenS] = String(c).split('/'); const n = toBytes(net); if (!n || n.v !== a.v) continue;
const len = lenS === undefined ? (n.v === 4 ? 32 : 128) : Number(lenS); if (!(len >= 0 && len <= (n.v === 4 ? 32 : 128))) continue;
let ok = true; for (let i = 0; i < len; i++) { const byte = i >> 3, bit = 7 - (i & 7); if (((a.b[byte] >> bit) & 1) !== ((n.b[byte] >> bit) & 1)) { ok = false; break; } }
if (ok) return true;
}
return false;
}