vms-8c2: DECnet Phase IV file COPY (FAL/DAP) — object-17 server + DAP codec + COPY client - #1096
Conversation
|
PROOF-RUN: workflow_dispatch run #34408801852 fired on work/vms-8c2 — this is the heavy leg that runs the booted acceptance battery, where DECNETD.EXE --fal-accept-test proves the FULL inbound-FAL COPY on real /dev/vms: real SYSUAF/Purdy auth (GUEST/GUEST accepted, wrong password + DISABLED refused) then a sequential file transferred BOTH directions through real DAP + real RMS over the ACP, byte-verified. The PR-trigger run is FAST-tier only (no booted battery). Follow-on filed: vms-ea8 (outbound COPY client wired into DCL over the datalink + advanced DAP). |
20ad921 to
5238ee8
Compare
|
Updated proof run on the final SHA (5238ee8, after a CMake hardening that guards the ASan/UBSan flags behind a compiler+link support check so no CI toolchain fails to build the fuzz test): workflow_dispatch run #34409023435. This is the run to read for the --fal-accept-test heavy leg; the earlier #34408801852 is on a superseded SHA. |
…s (vms-8c2/#1096) The guide was grounded on origin/main (pre-#1096), so §4 documented COPY-over- DECnet as not-yet-built. Since the guide (#1097) and FAL (#1096) both land in V0.6-13, augment §4 + the status table to the post-#1096 state: authenticated inbound FAL (object 17, connect-carried creds checked via SYSUAF/Purdy + disabled gate BEFORE accept, bad-pw refused), real DAP codec (bounded/fuzz-clean), RMS-over- ACP. Honest deferred: outbound DCL COPY bridge reports %COPY-I-NETNOTWIRED (rd vms-ea8), advanced DAP, byte-level stock-VAX interop. Clarified the ONE-authenticator bullet (interactive→LOGINOUT via $CREPRC; FAL→SYSUAF directly). MUST merge AFTER #1096 (it describes FAL, which #1096 delivers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2
5238ee8 to
717d4e1
Compare
… codec + COPY client
Add the DECnet file-transfer layered product behind $ COPY node"user pw"::file:
the File Access Listener (Session Control object 17) server, the DAP (Data
Access Protocol) message codec, and the COPY-node client logic.
- DAP codec (src/vmsdecnet/dap/dnet_dap.{c,h}): pure, bounded, self-round-tripping
encode/decode of CONFIGURATION/ATTRIBUTES/ACCESS/CONTROL/DATA/STATUS/NAME/
ACCESS-COMPLETE. Clean-room (Rule 8): message set + generic framing from the
public DAP spec; sequence + carried values (filename, resolved full spec, owner
UIC, verbatim records) from docs/oracle/vax-copy-fal-dap.* (vms-cd3). Fuzzed
200k inputs + every truncated prefix, ASan/UBSan-clean.
- FAL server + COPY client (src/vmsdecnet/fal/dnet_fal.{c,h}): a SECURITY surface.
An inbound object-17 connect CARRIES username+password (oracle §1, the opposite
of CTERM); FAL authenticates them through THE ONE faithful authenticator
(sysuaf_lookup + sysuaf_authenticate Purdy + the disabled-account gate, the same
path LOGINOUT/SSHD use) BEFORE accepting the link and REFUSES with an NSP
disconnect on a bad password (INV-6 — no file served on an unauthenticated
connect). File I/O is rms_textfile_* (RMS over the ODS-2 ACP), fail-honest with
no /dev/vms — no userspace fallback that fakes a transfer (Rule 9). No
fork/exec/openpty/dup2, no raw-fd/termios file mechanics.
- Bounded FAL credential decoder (dnet_fal_access_decode in dnet_cterm.c): the FAL
counterpart to the CTERM connect parse — it RETAINS the password (which FAL must
authenticate) into a caller buffer the server wipes; the CTERM "never retains a
password" invariant stays intact for every non-FAL path. Fuzz-clean.
- DECNETD.EXE --fal-accept-test: the FULL proof (hard gate in the booted battery on
real /dev/vms) — real SYSUAF auth (GUEST/GUEST accepted, wrong password + DISABLED
refused) then a sequential file transferred BOTH directions through real DAP over
an NSP link + real RMS, byte-verified. --fal-selftest: the honest floor (runs
anywhere) — a real object-17 connect carrying the creds refused with an NSP
disconnect when unauthenticated, plus the threaded DAP-over-NSP transport pump.
- DCL COPY (dcl_cmd_file.c): a NODE:: spec routes to the FAL/DAP path and reports
honestly (%COPY-I-NETNOTWIRED) rather than mis-copying it locally; the outbound
COPY-over-datalink bridge from a DCL process is a tracked follow-on.
- Compat SSOT: decnet$dap + decnet$fal added; decnet$node-filespec-syntax updated;
docs/compatibility-surface.md re-rendered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2
…fal-accept-test's real auth + real file I/O run The booted --fal-accept-test heavy leg was RED: GUEST/GUEST auth, the DISABLED gate, the source-file create, and the GET link-up all FAILED on the real executive, while --fal-selftest (no executive) passed. Root cause was NOT the FAL logic: DECNETD.EXE is a static musl image whose FAL half reaches the RMS record services (rms_textfile.c) and the binary $UAFDEF SYSUAF engine (sysuaf.c) through LIBVMS's `#pragma weak` seam. Under a static link a weak-only reference does not extract the defining archive member, and DECNETD linked neither vmsrms nor any strong reference into it -- so sys$open and ovmx_sysuaf_read_user stayed NULL, rms_services_present() read FALSE, and sysuaf_lookup() returned "miss" before any ACP call. Auth and file creation then failed honestly (INV-6) even though LOGINOUT -- which carries the same anchor (loginout_rms_bind.c) -- authenticates GUEST fine on the same image. Fix: link vmsrms into DECNETD.EXE and add decnetd_rms_bind.c, a strong-reference anchor for the seven RMS services + the two SYSUAF engine readers, so the static linker extracts rms_core.o + sysuaf_live.o. This is the same weak-seam trap provision_rms_bind.c / loginout_rms_bind.c / tests/qemu/rms_acp_bind.c already close. Verified: nm now shows sys$open/$create/$get/$put/$connect/$close + ovmx_sysuaf_read_user/_uic DEFINED in DECNETD.EXE (absent before). --fal-selftest stays green (2 passed, 0 failed). No FAL logic, DAP codec, or auth check weakened (Rule 9 / INV-6); the pre-existing benign fab$b_bln -Woverflow is untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2
…L PASS assertions so the booted --fal-accept-test goes green
With the RMS/SYSUAF weak-seam bound (prior commit), the booted --fal-accept-test
went from 3/4 to 11/1: GUEST/GUEST auth, wrong-password refusal, source-file
create over the ACP, and both-direction byte-match all pass on the real
executive. Two residual defects, both real:
1. The shipped distro/rootfs SYSUAF.DAT was STALE -- it carried only GUEST +
SYSTEM, but tools/mksysuaf.c's seed has grown to 7 accounts including the
DISABLED account (DISUSER, correct password DISABLED; rd vms-f40). So FAL's
dnet_fal_authenticate("DISABLED","DISABLED") hit sysuaf_lookup MISS and
returned SS$_INVLOGIN instead of SS$_NOPRIV -- the DISUSER gate was never
reached. vms-f40's CTERM test did not catch this because LOGINOUT refuses
DISABLED identically whether the account is DISUSER or absent (both ->
"authorization failure"); FAL distinguishes them (NOPRIV vs INVLOGIN), which
is what exposed the stale seed. Fix: regenerate SYSUAF.DAT with the current
byte-reproducible mksysuaf (deterministic salt, no wall-clock -> stable
bytes), so the on-disk seed matches the generator of record. GUEST is
unchanged (same deterministic record) and no lifetime is set, so no account
is password-expired. This is seeding the test account correctly -- the auth
check itself is untouched (INV-6).
2. FA_CHECK printed a label only on FAILURE, so a fully-passing run omitted the
very PROPERTY strings the booted battery greps for (a wrong password REFUSED,
DISABLED refused, records BYTE-MATCH the source) -- making those must_have
greps satisfiable only when the assertion FAILED (inverted). Emit " PASS:
<msg>" on success too, matching the sibling CT_CHECK house style. This adds
evidence on pass; it weakens nothing (pass/fail counts and verdict unchanged).
--fal-selftest stays green (2 passed, 0 failed). Regenerated SYSUAF verified to
carry DISABLED with DISUSER; the ACP byte-exact reader (Prolog-3 header) is
content-agnostic, so no gate hardcodes the old bytes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2
… must_have The booted --fal-accept-test core went fully green (DECNETD-I-FALACCEPT, 12 passed, 0 failed; DECNETD-FAL-ACCEPT: PASS), but one battery assertion still failed: the wrong-password must_have. must_have matches with `grep -qiF` (fixed string), and its pattern was single-quoted as 'is REFUSED (SS\$_INVLOGIN) -- a fake would pass it' -- inside single quotes bash does NOT process `\$`, so the literal searched for was `SS\$_INVLOGIN` (with a backslash), which cannot match the real output `SS$_INVLOGIN`. Drop the errant backslash; single quotes already prevent `$` expansion, so 'SS$_INVLOGIN' is the correct literal. Verified against the real assertion line: the fixed pattern matches, the old one did not. This corrects the assertion to match the property FAL actually prints -- it weakens nothing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2
…shipped seed
Regenerating distro/rootfs SYSUAF.DAT to carry the full 7-account seed (adding
the DISABLED fixture the FAL accept-test needs) changed one byte of the Prolog-3
prolog VBN 1 -- offset 10 went 0x19 -> 0x1c (the index field reflecting 7 records
vs the stale file's 2). test_syssvc_dirlogical_acp.c holds a 16-byte golden of
the shipped file's leading bytes ("kept in sync with the shipped binary file",
vms-586) and its byte-exact $GET/IO$_READVBLK check (Kernel Executive shard 1/6)
went RED. Update the golden's one changed byte to match the regenerated file
(verified byte-for-byte). This refreshes a golden to the legitimately-changed
seed; the assertion still reads VBN 1 byte-exact off the real ODS-2 volume and
compares the real shipped prolog -- it is not weakened.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2
8c88647 to
b5e1f50
Compare
* docs: add DECnet Phase IV configuration + usage guide (vms-30e) Operator-facing guide for the DECnet layered product, the sibling of docs/cluster-configuration-guide.md. Covers NCP node/executor configuration, inbound and outbound SET HOST, and honestly scopes out COPY/FAL-DAP as not-yet-implemented (decnet$task-to-task is absent in the register; cmd_copy() has no NODE:: handling and the FAL/DAP oracle capture is ground truth for a future implementation, not a shipped feature). Every capability claim is grounded in docs/compat/facilities/decnet.yaml and verified against ncp.c, dcl_cmd_set.c, and dcl_cmd_file.c on origin/main. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2 * docs: DECnet guide §4 — describe the authenticated FAL/DAP file access (vms-8c2/#1096) The guide was grounded on origin/main (pre-#1096), so §4 documented COPY-over- DECnet as not-yet-built. Since the guide (#1097) and FAL (#1096) both land in V0.6-13, augment §4 + the status table to the post-#1096 state: authenticated inbound FAL (object 17, connect-carried creds checked via SYSUAF/Purdy + disabled gate BEFORE accept, bad-pw refused), real DAP codec (bounded/fuzz-clean), RMS-over- ACP. Honest deferred: outbound DCL COPY bridge reports %COPY-I-NETNOTWIRED (rd vms-ea8), advanced DAP, byte-level stock-VAX interop. Clarified the ONE-authenticator bullet (interactive→LOGINOUT via $CREPRC; FAL→SYSUAF directly). MUST merge AFTER #1096 (it describes FAL, which #1096 delivers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…proof hard-gates all three rails The DCL/SHOW acceptance battery's DECnet CTERM (vms-f40) and NETACP isolation (vms-9ab) sections were an honest "emits a note, asserts nothing" gap on the VAX and Alpha rails: DECNETD.EXE was in the x86_64 shipped image set and the vax ovmx-images CMake aggregate, but was never staged onto the runtimes those two rails actually boot for acceptance, so the auth proof never ran there. - tests/lab-vax/stage_sysvol.sh: DECNETD.EXE joins the VAX sysvol's BOOT_IMAGES list. - tests/lab-vax/run-boot.sh: build_boot_image_set() (feeds stage_sysvol.sh for the acceptance/sysboot-single runtime) now also cross-builds DECNETD.EXE via `cmake --build --target decnetd_exe` under the vax toolchain, and master_system_volume()'s hard content gate now requires it on the mastered volume. - tools/cross-alpha/build-alpha-bootimage.sh: DECNETD.EXE joins the Alpha boot image's staged SYSEXE set and its mastered-ODS-2 content gate (it already cross-builds via the unconditional vmsdecnet CMake subdirectory; Alpha is Linux-ABI, so it links against libdatalink's AF_PACKET backend, same as x86_64). - distro/Dockerfile.bootable: corrected the stale ~line-636 comment claiming DECNETD.EXE "needs the netbsd-vax userspace port" -- its datalink goes only through src/libdatalink's scs_datalink_* abstraction, which already ships both backends this facility needs. - tests/qemu/lib/dcl_acceptance_battery.sh: flipped both sections' "DECNETD.EXE absent" branch from `note` (asserts nothing) to `bad` (hard FAIL) on all three rails -- the note path is now unreachable in normal operation; if a staging regression ever drops the image off a rail again, the battery reds instead of silently passing (INV-6). Left a scope note that FAL's auth proof (#1096, not yet merged) needs no rail-staging work of its own once it lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2
…VAX + Alpha (#1099) * vms-c1f: stage DECNETD.EXE onto VAX + Alpha so the DECnet CTERM auth proof hard-gates all three rails The DCL/SHOW acceptance battery's DECnet CTERM (vms-f40) and NETACP isolation (vms-9ab) sections were an honest "emits a note, asserts nothing" gap on the VAX and Alpha rails: DECNETD.EXE was in the x86_64 shipped image set and the vax ovmx-images CMake aggregate, but was never staged onto the runtimes those two rails actually boot for acceptance, so the auth proof never ran there. - tests/lab-vax/stage_sysvol.sh: DECNETD.EXE joins the VAX sysvol's BOOT_IMAGES list. - tests/lab-vax/run-boot.sh: build_boot_image_set() (feeds stage_sysvol.sh for the acceptance/sysboot-single runtime) now also cross-builds DECNETD.EXE via `cmake --build --target decnetd_exe` under the vax toolchain, and master_system_volume()'s hard content gate now requires it on the mastered volume. - tools/cross-alpha/build-alpha-bootimage.sh: DECNETD.EXE joins the Alpha boot image's staged SYSEXE set and its mastered-ODS-2 content gate (it already cross-builds via the unconditional vmsdecnet CMake subdirectory; Alpha is Linux-ABI, so it links against libdatalink's AF_PACKET backend, same as x86_64). - distro/Dockerfile.bootable: corrected the stale ~line-636 comment claiming DECNETD.EXE "needs the netbsd-vax userspace port" -- its datalink goes only through src/libdatalink's scs_datalink_* abstraction, which already ships both backends this facility needs. - tests/qemu/lib/dcl_acceptance_battery.sh: flipped both sections' "DECNETD.EXE absent" branch from `note` (asserts nothing) to `bad` (hard FAIL) on all three rails -- the note path is now unreachable in normal operation; if a staging regression ever drops the image off a rail again, the battery reds instead of silently passing (INV-6). Left a scope note that FAL's auth proof (#1096, not yet merged) needs no rail-staging work of its own once it lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2 * vms-c1f: fix sysvol_master_vax ctest + build_vax_images for the DECNETD.EXE stage-list add stage_sysvol.sh's BOOT_IMAGES now requires DECNETD.EXE (previous commit), which broke two callers that fed it an images-dir without one: - tests/integration/test_sysvol_master_vax.sh: the host ctest synthesizes stand-in .EXE images and never included DECNETD.EXE, so stage_sysvol.sh died "boot image missing from images dir" (caught by CI: Build & Test -> sysvol_master_vax FAILED). Added a DECNETD.EXE stand-in + its round-trip/byte-exact assertions, matching the other four. - tests/lab-vax/run-boot.sh build_vax_images() (the install mode's VAX_IMAGES_DIR, feeding stage_sysvol.sh --distribution for the distribution volume): added DECNETD.EXE to both the `need` list and the copied-out image set from the ovmx-images cmake aggregate, which already builds it. Verified locally: built vmsfs_master via `cmake --build --target vmsfs_master`, ran test_sysvol_master_vax.sh directly -- ALL PASS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cated SET HOST (hard-gated x86_64+Alpha+VAX) Version bump (identity + os-release in step, INV-1 SSOT gate). V0.6-13 ships: - DECnet Phase IV file COPY (FAL/DAP): object-17 FAL server + DAP codec + COPY client, authenticated against the real SYSUAF/Purdy with RMS-over-ACP transfer, byte-verified both directions (#1096, vms-8c2). - The authenticated inbound SET HOST -> LOGINOUT proof is now a HARD GATE on all three rails: DECNETD.EXE staged onto the VAX sysvol + Alpha boot image, so DECNETD-CTERM-ACCEPT + DECNETD-ISOLATION assert+PASS on x86_64 + Alpha + VAX — the login frontier is substrate-agnostic (#1099, vms-c1f). - DECnet Phase IV configuration + usage guide (#1097, vms-30e). - Compatibility-register honesty: cluster-dlm evidence repointed off deleted src/vmsscs paths to the executive-resident src/kernel-core, and the 4 cluster-dlm rows whose multi-node /dev/vms proof was retired in #1052 downgraded verified->implemented (#1100/#1101; multi-node proof re-establishment gated in vms-1ee). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018q4jvj6GCkdbYjRvpy7Vwu
vms-8c2 — DECnet Phase IV file COPY (FAL/DAP)
The file-transfer layered product behind
$ COPY node"user pw"::file— the FAL (File Access Listener, DECnet Session Control object 17) server, the DAP message codec, and the COPY-node client. Extends the merged P5 NETACP / NSP / CTERM frontier; reverts nothing.Oracle:
docs/oracle/vax-copy-fal-dap.*(rd vms-cd3, real VAX↔VAX COPY).What landed
src/vmsdecnet/dap/dnet_dap.{c,h}) — pure, bounded, self-round-tripping encode/decode of CONFIGURATION/ATTRIBUTES/ACCESS/CONTROL/DATA/STATUS/NAME/ACCESS-COMPLETE. Clean-room (Rule 8): message set + generic framing from the public DAP spec; sequence + carried values (filename, resolved full spec, owner UIC, verbatim records) from the oracle. Fuzzed 200k inputs + every truncated prefix, ASan/UBSan-clean.src/vmsdecnet/fal/dnet_fal.{c,h}) — a security surface. An inbound object-17 connect carries username+password (oracle §1, opposite of CTERM); FAL authenticates them through the one faithful authenticator (sysuaf_lookup+sysuaf_authenticatePurdy + the disabled-account gate — the same path LOGINOUT/SSHD use) before accepting the link and refuses with an NSP disconnect on a bad password (INV-6 — no file served on an unauthenticated connect). File I/O isrms_textfile_*(RMS over the ODS-2 ACP), fail-honest with no/dev/vms— no userspace fallback that fakes a transfer (Rule 9). No fork/exec/openpty/dup2, no raw-fd/termios file mechanics.dnet_fal_access_decodeindnet_cterm.c) — the FAL counterpart to the CTERM connect parse; retains the password FAL must check, wipes it after; the CTERM "never retains a password" invariant + test stay intact.DECNETD.EXE --fal-accept-test(hard gate in the booted battery on real/dev/vms): real SYSUAF auth (GUEST/GUEST accepted, wrong password + DISABLED refused) then a sequential file transferred both directions through real DAP + real RMS, byte-verified.DECNETD.EXE --fal-selftest(honest floor, runs anywhere): a real object-17 connect carrying the creds refused with an NSP disconnect when unauthenticated, plus the threaded DAP-over-NSP transport pump. PASS locally.%COPY-I-NETNOTWIRED); the outbound COPY-over-datalink bridge from a DCL process is a tracked follow-on (same gap SET HOST's outbound client had until vms-f54).decnet$dap+decnet$faladded,decnet$node-filespec-syntaxupdated;docs/compatibility-surface.mdre-rendered.Local proof (this PR)
Proof run
--fal-accept-test(real auth + real RMS transfer both directions) is a heavy leg that runs in the booted acceptance battery on real/dev/vms. Fired viagh workflow run ci.yml --ref work/vms-8c2— see PROOF-RUN below.Honest floors / filed follow-ons (INV-6, never faked)
🤖 Generated with Claude Code
https://claude.ai/code/session_01T4csyFSMUsS8k1D2MgMxk2