Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
219 changes: 219 additions & 0 deletions prompts/m4-vslsec-vsllog-kickoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
---
title: "VSL/MSL M4 — VSLSEC + VSLLOG: the security (S5) and audit (S3) seams"
status: ready
created: 2026-06-16
doc_type: [PROMPT]
for: a fresh implementation session (cross-repo, leaf-first; MSL seam leaf(s) → VSLSEC + VSLLOG in v-stdlib)
plan: docs/vsl-msl/vsl-implementation-plan.md
tracker: docs/vsl-msl/vsl-implementation-tracker.md
---

# VSL/MSL M4 — `VSLSEC` (security, S5) + `VSLLOG` (audit, S3)

The next milestone in the horizontal seam build-out (§12.2): **security +
audit**. `VSLSEC` binds the identity/crypto seam to Kernel
(`^XUSHSH`/`$$ENCRYP^XUSHSH`, `DUZ`/#200, `^XUSEC`, OPTION #19 context);
`VSLLOG` binds the observability sink to a **FileMan audit file** (and,
optionally, a MailMan alert). Risk **R3 — Kernel auth impedance** (VSLSEC) and
the audit-sink durability problem the §6.2 log-egress example motivates (VSLLOG).

M4 is **parallel-safe** with the owed M2 tail and the deferred v-pkg DD-install
track; it does not wait on them.

## Where we are (snapshot, 2026-06-16)

- **M1 COMPLETE** (`STDENV→VSLCFG→VPNG`) · **M2 functionally complete** (`STDNET`
+ `VSLIO`, socket seam) · **M3 COMPLETE + MERGED** (`STDKV` + `VSLFS`, the
storage seam S1 — dual-engine 7/7, DIERR→`,U-VSL-FS-DIERR,`).
- **MSL is at `v0.9.0`** (STDENV + STDNET + STDKV seams); v-stdlib `main` pins
`msl_ref: v0.9.0` and has **VSLCFG + VSLIO + VSLFS** (all merged).
- **The seam machinery is well-worn**: `@seam`→snapshot + bump-forcer; v-stdlib
`check-msl-pin` fetches MSL's contract at the pinned tag; the four drift gates.
- **`check-icr` now accepts a notional `@icr DBS`/`notional` marker** (the DBIA
registry is a human-curated FORUM list, not enforced — see the HARD RULE in
shared memory `notional-dbia-not-a-blocker.md` + plan §5.4). Kernel ICRs
(`^XUSHSH`, `^XUSEC`, `XUS…`) ARE usually numbered — but **ground every one via
`corpus-researcher`** and fall back to the notional marker if the corpus has no
number. Never re-open a missing number as a blocker.
- **`VSLFS` is the reusable FileMan-DBS record writer** — `$$set`/`$$get`/
`$$exists`/`$$kill` over `(file,iens,field)` with the DIERR→`$ECODE` contract.
- Both engines up: `vehu` (YDB), `foia-t12` (IRIS), driver stack only.

## The open design questions to resolve FIRST (then don't re-litigate)

1. **The security seam splits AT the waterline — most of `VSLSEC` has NO MSL
counterpart.** Portable token/credential crypto (HMAC, constant-time compare,
digests) already lives in `STDCRYPTO`. The **authorization decision** — *does
`DUZ` hold this `^XUSEC` key / this OPTION #19 context?*, and the principal→
`DUZ`/#200 binding — is **inherently VistA** (it cannot run on a bare engine),
so it has **no portable MSL seam**: `VSLSEC` is a *VistA-only* adapter for
that part (like `VSLIO`'s server side staying out of the seam). **Decide
early:** does `VSLSEC` ALSO bind `^XUSHSH`/`$$ENCRYP^XUSHSH` as a back end for
an `STDCRYPTO` *hash/compare* seam (→ tag a minimal `@seam` on STDCRYPTO),
**or** is `VSLSEC` purely the authz layer (`$$hasKey`/`$$inContext`/`$$duz`)
with NO MSL seam at all? **Recommendation:** keep the seam **minimal** — bind
only what a real consumer needs. The §12.2 VSLSEC row + architecture §3.4 are
the ground truth; read them before naming entry points. Portable crypto stays
in `STD*`; the VistA authorization decision lives in `VSLSEC` (architecture
§3.4, verbatim).
2. **Where is the `STDLOG` sink seam, and does `VSLLOG` reuse `VSLFS`?** `STDLOG`
is the portable structured logger; the **sink** is the seam `VSLLOG` backs
(a FileMan audit file). **Decide:** (a) does `STDLOG` already expose a
pluggable sink to tag `@seam`, or does the seam need a small new entry point;
and (b) **`VSLLOG` should REUSE `VSLFS`** for the FileMan record writes
(v→v composition is allowed — both are layer `v`; only `v→m` is one-way), not
re-bind `UPDATE^DIE` itself — `VSLLOG` adds only the log-record→FileMan-fields
mapping (+ optional MailMan alert). **Recommendation:** reuse `VSLFS`; do NOT
duplicate the DBS binding (waterline §9 no-dup applies within `v` too).
3. **How are the test fixtures provided (live, safe)?** Mirror M3's resolution:
use **EXISTING low-risk entries via the probe pattern**, deferring any
data-DD install to the v-pkg track.
- **VSLSEC:** an existing `DUZ`/#200 user (e.g. `DUZ=1`), an existing
`^XUSEC(KEY,DUZ)` key, and an existing OPTION #19 context the test user
holds — probe for one that's present (read-only), assert the authz decision;
do NOT grant/revoke real keys. For `^XUSHSH` hashing, hash a throwaway
string and assert determinism (no persisted state).
- **VSLLOG:** an **existing low-risk FileMan file** for the audit records
(the #8989.51-style throwaway-record pattern VSLFS used), or a dedicated
audit file via the deferred v-pkg DD-install enabler. **Recommendation:**
existing file first (do NOT block VSLLOG-green on the DD installer).

## Decisions already made (do not re-litigate)

1. **Leaf-first, cross-repo, one writer per repo** (as M1–M3): any **new/changed
MSL seam** is authored + **tagged** (`v0.10.0`) in m-stdlib FIRST; only then
does v-stdlib re-pin `msl_ref` → `v0.10.0` and bind it. If M4 needs NO MSL
seam change (VSLSEC authz is VistA-only; STDLOG's sink already exists), the
MSL leg may be a no-op and no new tag is cut — decide per Q1/Q2. Never edit
two repos in one session. Cutting the MSL tag is an explicit user action.
2. **`VSLSEC` + `VSLLOG` live in v-stdlib** (beside VSLCFG/VSLIO/VSLFS), layer
`v`. They contain ONLY the VistA binding; portable logic stays in `STD*`
(called up). `VSLLOG` reuses `VSLFS` for FileMan writes (no DBS re-bind).
3. **Every L4 call is `@icr`-tagged + grounded via `corpus-researcher`.** Kernel
(`^XUSHSH`, `^XUSEC`, `XUS…` context, `$$ENCRYP^XUSHSH`), MailMan, and the
FileMan DBS (reused via VSLFS). Do NOT trust the plan's prose — verify each ICR
number + `@source` anchor; use the **notional `@icr DBS`/`notional` marker**
for any documented-Supported call the corpus has no number for (the gate
accepts it; see `notional-dbia-not-a-blocker.md`).
4. **Error contract:** loud failures map to clean `,U-VSL-SEC-…,` / `,U-VSL-LOG-…,`
`$ECODE` (with `$$lastError^VSLSEC()` / `$$lastError^VSLLOG()` carrying detail)
— the same loud-failure posture as VSLFS's DIERR mapping and VSLIO/STDNET's
TLS guards. An authz DENY is a normal `0`/false return, NOT an error; a
malformed call or a FileMan/Kernel fault is the loud `$ECODE`.
5. **Dual-engine is the exit criterion** (single-engine first). Kernel auth +
FileMan are VistA-portable — verify on both `vehu` and `foia-t12`; add a
`$ZVERSION` arm only if a primitive genuinely diverges (VSLFS needed none).

## Resume prompt

```
Start VSL/MSL M4 — VSLSEC (security seam, S5) + VSLLOG (audit seam, S3). Bind the
identity/crypto seam to Kernel (^XUSHSH / $$ENCRYP^XUSHSH, DUZ/#200, ^XUSEC,
OPTION #19 context) as VSLSEC, and the observability sink to a FileMan audit file
(+ optional MailMan alert) as VSLLOG — VSLLOG REUSING VSLFS for the FileMan record
writes (v->v composition; no DBS re-bind). Prove GREEN on BOTH engines (vehu YDB,
foia-t12 IRIS) over the driver stack. Single-engine first; dual-engine is the exit.

RESOLVE THE DESIGN QUESTIONS FIRST (see the kickoff): (Q1) the security seam splits
at the waterline — VSLSEC's authz (hasKey/inContext/DUZ bind) is VistA-only with NO
MSL seam; portable crypto stays in STDCRYPTO; decide whether to also bind ^XUSHSH as
an STDCRYPTO hash/compare back end. (Q2) STDLOG sink seam home + VSLLOG reuses VSLFS.
(Q3) test fixtures = EXISTING low-risk entries via the probe pattern (an existing
DUZ/#200 user + ^XUSEC key + context option for VSLSEC; an existing low-risk file
for VSLLOG audit records), deferring any data-DD install to a v-pkg track.

CROSS-REPO, LEAF-FIRST, ONE WRITER PER REPO: if a new/changed MSL seam is needed,
author + TAG it in m-stdlib FIRST (new tag v0.10.0), THEN bind it in v-stdlib
(re-pin msl_ref v0.9.0 -> v0.10.0). If M4 needs no MSL seam change, no new tag.
Never edit two repos in one session.

START BY READING (in order):
1. docs/vsl-msl/msl-vsl-architecture.md §3.4 (Kernel identity/authz) + §3.6/§3
(MailMan/audit) + docs/vsl-msl/msl-vsl-coordination-implementation-plan.md
§5.1 (S5 + S3 rows), §5.4 (the @icr gate — now notional-aware), §5.5
(@source), §12.2 (the VSLSEC + VSLLOG acceptance rows).
2. v-stdlib/src/VSLFS.m + VSLIO.m + VSLCFG.m + their tests + docs/memory/
{m3-vslfs,m2-vslio,t1.2-vslcfg}.md — the adapter pattern, the @icr/@source/
pin gate wiring, the live-driver recipe, the DIERR/loud-error posture, and
how VSLFS exposes set/get/exists/kill (VSLLOG reuses it).
3. m-stdlib/src/STDCRYPTO.m + STDLOG.m (+ docs/modules/) — confirm what portable
surface already exists (crypto hash/compare; the log sink), and whether a new
@seam tag is needed; m-stdlib/docs/memory/m3-stdkv-storage-seam.md (the
leaf-first + @seam + tag-and-repin rhythm to copy).
4. docs/memory/notional-dbia-not-a-blocker.md (shared) — the @icr notional rule
+ how gen-icr.py's NOTIONAL_MARKERS works; v-stdlib/tools/gen-icr.py.
5. ~/vista-cloud-dev/CLAUDE.md + v-stdlib/CLAUDE.md — the m/v waterline, the
ENGINE-ACCESS HARD RULE (driver stack only), and the Increment Protocol.

THE WORK (TDD red-first, hard rule; like M3):
LANE A (m-stdlib, only IF a seam change is needed): tag/extend the @seam
(STDCRYPTO hash/compare and/or STDLOG sink), tests green both engines, the 4
drift gates + bump-forcer green, increment + (user) tag MSL v0.10.0.
LANE B (v-stdlib, after any v0.10.0): VSLSEC + VSLLOG. Re-pin if Lane A ran.
tests/VSLSECTST.m + VSLLOGTST.m FIRST (red, safe defaults): VSLSEC hash
determinism + hasKey/inContext over existing safe entries + a loud
,U-VSL-SEC-..., on a Kernel fault; VSLLOG writes an audit record (via VSLFS),
reads it back, and maps a failure to ,U-VSL-LOG-.... src/VSLSEC.m + VSLLOG.m:
the VistA binding ONLY, each L4 call @icr/@source-tagged (grounded via
corpus-researcher; notional marker where the corpus has no number).

ENGINE RECIPES (from m3/t1.2 memory):
m test --engine ydb --docker vehu --chset m --routines src --routines <m-stdlib>/src tests/VSLSECTST.m
m test --engine iris --docker foia-t12 --namespace VISTA --routines src --routines <m-stdlib>/src tests/VSLSECTST.m
m vista exec --engine ydb|iris --transport docker '<M>' (+ M_YDB_*/M_IRIS_* env for ad-hoc DD probes)
(Driver stack ONLY — never raw docker exec / iris session.)

VERIFICATION (M4 "done"):
• VSLSECTST + VSLLOGTST green on BOTH engines: VSLSEC hash/compare + authz
decision over existing safe entries, loud ,U-VSL-SEC-...,; VSLLOG audit
write+read via VSLFS, loud ,U-VSL-LOG-....
• Boundaries green: check-msl-pin (@v0.10.0 if Lane A ran, else @v0.9.0) /
check-icr (every Kernel/FileMan/MailMan call Supported-or-notional + declared,
no direct VistA-global access) / check-citations. make check-fast clean.
• No regression: m-stdlib + v-stdlib's VSLCFG/VSLIO/VSLFS + vpng unchanged.

DO NOT (scope guards):
• Do NOT edit two repos in one session; tag any MSL leaf first, then the VSL.
• Do NOT re-bind FileMan DBS in VSLLOG — reuse VSLFS (no duplication).
• Do NOT reimplement portable crypto in VSLSEC — STDCRYPTO owns it; VSLSEC is
the VistA authz decision + the Kernel hash back end only.
• Do NOT grant/revoke real ^XUSEC keys or alter real users — probe existing
safe entries read-only; do NOT block green on a data-DD install (deferred).
• Do NOT re-open a missing ICR number as a blocker (notional marker is fine).
• Merges + any MSL re-tag stay user actions.

INCREMENT PROTOCOL (per repo, when green):
Lane A (if run): memory + module-tracker + docs/modules/<m>.md; commit/push;
(user) tag v0.10.0.
Lane B: memory v-stdlib/docs/memory/m4-vslsec-vsllog.md; flip the M4 row in
docs/vsl-msl/vsl-implementation-tracker.md (docs repo — SEPARATE commit);
commit/push the v-stdlib branch (e.g. m4-vslsec-vsllog). Co-Authored-By trailer.

GOAL: the security + audit seams proven — VSLSEC binds identity/crypto to Kernel
(hash + the VistA authz decision) and VSLLOG durably writes audit records through
VSLFS to FileMan, both loud-on-failure and dual-engine green, all determinism
boundaries green. Then M5 (VSLBLD/VSLTASK — KIDS build + listener, §12.2) and the
§6.2 worked examples (S3 log egress, FHIR façade).
```

## Notes for the operator (not part of the resume prompt)

- **VSLSEC is mostly NOT a seam adapter.** Unlike VSLCFG/VSLIO/VSLFS (each backs a
portable MSL seam), the *authorization decision* has no bare-engine analog, so
VSLSEC is largely a pure-VistA module. That's expected per the architecture
(§3.4): "Portable token crypto stays in STD*; the VistA authorization decision
lives in VSL." Only the `^XUSHSH` hash back end (if pursued) mirrors a portable
STDCRYPTO seam. Don't force a seam where the capability is inherently VistA.
- **VSLLOG is the first v→v composition.** It reuses VSLFS rather than re-binding
FileMan DBS — the in-`v` analog of the waterline no-duplication rule. Confirm
`m arch check` is happy with a `VSL*`→`VSL*` call (it should be — the gate
forbids `v→` only below the line, and `m→v`; within `v` is fine).
- **Ground every Kernel ICR.** `^XUSHSH`/`$$ENCRYP^XUSHSH`, `^XUSEC`, the `XUS`
context APIs, and MailMan are documented in the Kernel guides — but the corpus
has been wrong before (XPAR at T1.2, CALL^%ZISTCP at M2). Verify each via
`corpus-researcher`; use the notional marker where no number exists.
- **The owed/parallel tracks** (non-blocking): the v-pkg FileMan-DD-install
enabler (would give VSLLOG a dedicated audit file + re-test VSLFS), STDNET's
IRIS leg, and tier-3 TLS. None gate M4.
- **If `foia-t12` is down**, recreate per the IRIS recipe in the t1.2/t1.3
memories; confirm `docker ps` healthy before the IRIS run.
Loading