code wiki / _hdl_build / nx_stage_alias.nx
nx_stage_alias.nx
buildroot/runtime/_hdl_build/nx_stage_alias.nx
about
nx_stage_alias.nx -- the missing RENAME BRIDGE in the build-over-API loop (seq983).
THE GAP: /api/build stages an artifact as <target>.sov.elf.new, but the deploy plane expects
per-target names -- cmd_selfswap renames a hardcoded nx_hostctl.new, and the deploy rows name
things like nx_mgmt_api.elf.new. Nothing reachable over the API could bridge those two names:
nx_fs_write is text-only (a binary would be corrupted), md_promote_staged only maps <n>.new -> <n>,
/api/promote maps <t>.sov.elf.new -> <t>.elf and refuses daemon/oracle names outright, and
/api/unpack writes only under buildroot/runtime at mode 0644. So the documented sequence
"build then deploy" could never actually stage a deployable artifact, and the established
workaround was to build off-hub and upload -- i.e. leave the sovereign API.
WHY THIS IS NOT A GENERAL FILE-COPY TOOL: a general copy primitive exposed over the API would be a
serious hazard. This is deliberately the narrowest thing that closes the gap:
- the target name is sanitized to [A-Za-z0-9_] only, so a path separator or .. can never appear;
- the source is ALWAYS <target>.sov.elf.new and the destination ALWAYS <target>.<suffix>, both in
the daemon cwd -- neither is caller-supplied as a path;
- the suffix is an allowlist of exactly {new, elf.new}; anything else is refused;
- the source must exist, be non-empty, and begin with the ELF magic \x7fELF -- so a failed build
that staged 0 bytes, or any non-ELF, is REFUSED rather than propagated into a deploy;
- the destination is written fresh and chmod 0755, because a promoted binary must be executable.
Refusals are LOUD and return non-zero; nothing is written on any refusal path.
license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_gate_verdict.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 27 | const SA_NAMEMAX: i64 = 120 |
| 28 | const SA_PATHMAX: i64 = 256 |
| 29 | const SA_COPYBUF: i64 = 262144 |
| 30 | const SA_MODE_X: i64 = 0x1ed // 0755 -- a promoted binary must stay executable |
| 31 | const SA_MODE_RW: i64 = 0x1a4 // 0644 -- creation mode before the chmod |
| 32 | const SA_ELF_0: i64 = 127 // \x7f |
| 33 | const SA_ELF_1: i64 = 69 // 'E' |
| 34 | const SA_ELF_2: i64 = 76 // 'L' |
| 35 | const SA_ELF_3: i64 = 70 // 'F' |
functions
| 37 | func sa_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 41 | func sa_streq(a: *u8, b: *u8) -> i64 |
| 51 | func sa_cat(dst: *u8, o: i64, src: *u8) -> i64 called by 1: main |
| 60 | func sa_name_ok(nm: *u8) -> i64 |
| 77 | func sa_suffix_ok(sfx: *u8) -> i64 |
| 84 | func sa_copy_elf(src: *u8, dst: *u8) -> i64 called by 2: sa_selftestmain calls 7: sys_openat_rdsys_mmapsys_readsys_closesys_openat_wrsys_write+1 |
| 113 | func sa_selftest() -> i64 |
| 168 | func main(argc: i64, argv: *i64) -> i64 |