code wiki / _hdl_build / nx_devcap_provision.nx
nx_devcap_provision.nx source
↩ module page · 76 lines · 4744 B
1// nx_devcap_provision.nx -- provision the DEV/CI API capability chain, sovereignly (operator 2026-07-02:
2// "get this all setup as api calls ... build our nishi lang to s class exceed"). Generates the HMAC secret
3// keyfile (32 random bytes from /dev/urandom, 0600 -- the file nx_dev_api's da_authz loads in prod, and the
4// file nx_cap_mint signs with), mints a `dev_build` capability valid for ~1 year, writes it to a token file,
5// and SELF-VERIFIES the full chain (capt_verify(keyfile-secret, minted-token, "dev_build", now) == CAPT_OK)
6// plus proves ISOLATION (a token minted with the const/dev secret does NOT verify against the keyfile secret).
7// Idempotent: reuses an existing keyfile so live caps keep verifying. Run once locally, then nx_aw_send the
8// keyfile to the NAS nishihost dir (0600) and keep the token operator-side (present as X-Nishi-Cap).
9// writes: dev_cap_secret.key (secret) + dev_cap.tok (an operator dev_build capability)
10// expect_exit: 0 license_tier: ORIGINAL
11import "nx_cap_token.nx"
12const DEV_MAGIC_31536000: i64 = 31536000
13const DEV_MAGIC_2048: i64 = 2048
14
15const KEYFILE: *u8 = "dev_cap_secret.key" as *u8
16const TOKFILE: *u8 = "dev_cap.tok" as *u8
17const DEV_CONST_SECRET: *u8 = "nishi-dev-cap-hmac-secret-v1-REPLACE-FROM-VAULT" as *u8
18
19func pw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
20func pn(v: i64) -> i64 { let b: *u8=sys_mmap(24); let n: i64=capt_catn(b,0,v); sys_write(1,b,n); return 0 }
21
22// read 32 bytes from /dev/urandom into out; 0 ok
23func fill_rand(out: *u8, n: i64) -> i64 {
24 let fd: i64 = sys_openat_rd("/dev/urandom" as *u8)
25 if fd < 0 { return 0 - 1 }
26 var got: i64 = 0
27 while got < n { let r: i64 = sys_read(fd, ((out as i64)+got) as *u8, n-got); if r<=0 { sys_close(fd); return 0-1 } got=got+r }
28 sys_close(fd)
29 return 0
30}
31
32func main() -> i64 {
33 pw("=== nx_devcap_provision: dev_build capability chain (keyfile + token + self-verify) ===\n" as *u8)
34 // 1. keyfile: reuse if present (idempotent), else generate 32 random bytes
35 let ksz: *i64 = sys_mmap(16) as *i64; ksz[0]=0
36 var secret: *u8 = sys_read_file(KEYFILE, ksz)
37 var klen: i64 = 0
38 if (secret as i64) != 0 { if ksz[0] > 0 { klen = ksz[0]; pw(" keyfile: reused existing ("); pn(klen); pw(" bytes)\n" as *u8) } }
39 if klen == 0 {
40 let kb: *u8 = sys_mmap(64)
41 if fill_rand(kb, 32) != 0 { pw(" cannot read /dev/urandom -> RED\n" as *u8); return 1 }
42 let kf: i64 = sys_openat_wr(KEYFILE, 0x180) // 0600
43 if kf < 0 { pw(" cannot write keyfile -> RED\n" as *u8); return 1 }
44 sys_write(kf, kb, 32); sys_close(kf)
45 secret = kb; klen = 32
46 pw(" keyfile: GENERATED 32 random bytes -> dev_cap_secret.key (0600)\n" as *u8)
47 }
48 // 2. mint a dev_build cap valid ~1 year, unique-ish nonce from the clock
49 let now: i64 = sys_now_realtime_sec()
50 let exp: i64 = now + DEV_MAGIC_31536000
51 let nonce: i64 = now
52 let tok: *u8 = sys_mmap(DEV_MAGIC_2048)
53 let tn: i64 = capt_issue(secret, klen, "dev_build" as *u8, 9, exp, nonce, tok, DEV_MAGIC_2048)
54 if tn <= 0 { pw(" mint failed -> RED\n" as *u8); return 1 }
55 let tf: i64 = sys_openat_wr(TOKFILE, 0x180)
56 if tf >= 0 { sys_write(tf, tok, tn); sys_close(tf) }
57 pw(" minted dev_build cap ("); pn(tn); pw(" bytes) -> dev_cap.tok (exp=+1yr)\n" as *u8)
58
59 // 3. self-verify the full authorized chain
60 var pass: i64 = 0
61 let v1: i64 = capt_verify(secret, klen, tok, tn, "dev_build" as *u8, 9, now)
62 if v1 == CAPT_OK { pw(" T1 keyfile-secret verifies the minted cap for dev_build: PASS\n" as *u8); pass=pass+1 } else { pw(" T1 FAIL v="); pn(v1); pw("\n" as *u8) }
63 // wrong tool -> DENY_TOOL
64 let v2: i64 = capt_verify(secret, klen, tok, tn, "other_tool" as *u8, 10, now)
65 if v2 == CAPT_DENY_TOOL { pw(" T2 cap does NOT grant other_tool (least-authority): PASS\n" as *u8); pass=pass+1 } else { pw(" T2 FAIL v="); pn(v2); pw("\n" as *u8) }
66 // ISOLATION: a cap minted with the const/dev secret must NOT verify against the keyfile secret
67 let ctok: *u8 = sys_mmap(DEV_MAGIC_2048)
68 let ctn: i64 = capt_issue(DEV_CONST_SECRET, capt_slen(DEV_CONST_SECRET), "dev_build" as *u8, 9, exp, nonce, ctok, DEV_MAGIC_2048)
69 let v3: i64 = capt_verify(secret, klen, ctok, ctn, "dev_build" as *u8, 9, now)
70 if v3 == CAPT_DENY_MAC { pw(" T3 const-secret cap REJECTED by keyfile secret (isolation): PASS\n" as *u8); pass=pass+1 } else { pw(" T3 FAIL v="); pn(v3); pw("\n" as *u8) }
71
72 pw("DEVCAP-PROVISION pass="); pn(pass); pw("/3" as *u8)
73 if pass==3 { pw(" verdict=GREEN -- keyfile + operator cap provisioned, chain self-verified\n" as *u8); return 0 }
74 pw(" verdict=RED\n" as *u8)
75 return 1
76}