Skip to content

feat(surface-client): expose write-attribution fields on Note/NoteSummary contracts - #195

Merged
unforced merged 1 commit into
mainfrom
ag-unforced-dev
Jul 16, 2026
Merged

feat(surface-client): expose write-attribution fields on Note/NoteSummary contracts#195
unforced merged 1 commit into
mainfrom
ag-unforced-dev

Conversation

@unforced

Copy link
Copy Markdown
Contributor

What

Adds createdBy, createdVia, lastUpdatedBy, lastUpdatedVia as optional string | null fields to the public Note and NoteSummary contracts in packages/surface-client. Strictly additive — every field is optional; legacy notes (predating attribution) carry null on these fields, not a breaking absence.

Why

The vault has carried write-attribution on note responses since vault#298, but surface-client's public contracts never exposed it, so consuming surfaces had no typed way to read it. This unblocks the app's ProvenanceBadge work (track 2, A2).

Semantics — factual only. These are provenance fields, not a semantic judgment: *By is the writing principal (JWT sub, operator, or token:<id> label), *Via is the interface the write arrived through (mcp, surface:<name>, agent:<id>, operator/cli, api). null means unknown/pre-attribution, distinct from any real principal. Do not infer "human vs AI" from these fields — a surface that wants that distinction maps known principals to it separately, on top of this contract.

Provenance note

Reimplemented from the 2026-07-15 Hermes-session handoff spec — the reviewed commit a9c5c36 exists only on the Hermes host's local clone (/root/Code/parachute) and was never pushed to origin, so it doesn't exist in this checkout (verified: absent from git log --all and git fsck --unreachable). Per the handoff note's own sanctioned fallback ("review/cherry-pick OR reimplement this narrowly"), this PR reimplements the four fields from the spec directly, with field names/types verified against the actual vault wire truth rather than the brief's memory of it — parachute-vault/core/src/types.ts:46-49 and core/src/notes.ts:2617-2620 confirm createdBy?: string | null etc., camelCase, exactly matching what's added here.

Compile-time contract

Adds packages/surface-client/src/__tests__/vault-types.contract.test.ts — a compile-time-only fixture (positive: fields as strings, as null, and omitted entirely; negative: @ts-expect-error on a wrong-typed value) that fails tsc if the barrel's exported Note/NoteSummary shapes drift. The package's own tsconfig.json excludes __tests__ from the build, and bun test alone doesn't typecheck (it transpiles, stripping types) — so this needed a new tsconfig.test.json, wired into both the package's typecheck script and the root typecheck:all.

That sibling config deliberately globs only src/__tests__/*.contract.test.ts, not the whole __tests__ directory: the rest of __tests__ has never been under tsc and carries pre-existing, unrelated type debt (stale .ts-extension imports needing allowImportingTsExtensions, a couple of drifted fixtures) that surfaced immediately when I tried the broader glob. Fixing that is out of scope for this narrow, additive change — flagging it as a follow-up rather than scope-creeping it in here.

Versioning

Stable patch bump per this repo's convention (docs/process/governance.md rule 2 + RELEASING.md: "parachute-surface ships stable patch bumps, not rc") — 0.3.40.3.5. src/version.ts regenerated via bun run gen-version; bun.lock synced. Package CHANGELOG updated (packages/surface-client/CHANGELOG.md).

Gates (all run in full, no piping through tail/head)

  • packages/surface-client bun run typecheck (tsc --noEmit && tsc -p tsconfig.test.json): clean, zero errors.
  • Root bun run typecheck:all (surface-host, surface-client, account-client, surface-server, surface-render, notes-ui, pebble-config, doc-schema, docs-editor, meeting-ingest, meeting-mcp, web/admin): clean, zero errors.
  • packages/surface-client bun test src/: 302 pass, 0 fail (608 expect() calls, 18 files — 17 pre-existing + the new contract fixture).
  • Root bun run test: 1599 pass, 0 fail (94 files, bun-native packages) + notes-ui (vitest) 1140 passed (115 files) + surface-render (vitest) 61 passed (8 files).
  • bun run build:surface-client: succeeds; verified dist/vault-types.d.ts carries the four new fields and no test fixture leaked into dist/.
  • bun run lint (biome, repo-wide): 26 errors, 8 warnings — identical before and after this diff (verified via git stash/stash pop against unmodified main; none of the flagged files are ones this PR touches). Pre-existing debt, not introduced here.

Compatibility

surface-client has real users — this change is additive-only. No existing field renamed, removed, or narrowed; no existing export removed from the barrel.

…mary contracts (0.3.5)

The vault has carried write-attribution (createdBy/createdVia/lastUpdatedBy/
lastUpdatedVia, vault#298) on note responses for a while; surface-client's
public Note/NoteSummary contracts didn't expose it. Adds all four as optional
`string | null` on both types — strictly additive, legacy notes carry null.

Reimplemented from the 2026-07-15 Hermes handoff spec (the reviewed commit
a9c5c36 exists only on the Hermes host and was never pushed to origin, so
this checkout cherry-picks nothing — verified field names/types directly
against parachute-vault core/src/types.ts + notes.ts).

Adds a compile-time-only contract fixture
(src/__tests__/vault-types.contract.test.ts) plus a narrowly-scoped
tsconfig.test.json (globs only *.contract.test.ts — the rest of __tests__
has pre-existing type debt never under tsc, deliberately not swept in) so
tsc actually catches contract drift; wired into both the package's own
typecheck script and the root typecheck:all.

Stable patch bump per this repo's surface-ships-stable-patches convention
(not rc) — 0.3.4 -> 0.3.5.
@unforced
unforced merged commit edf59ec into main Jul 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant