Skip to content

improvement(provenance): aggregate and attribute unrecorded durable reads - #7017

Merged
icecrasher321 merged 1 commit into
stagingfrom
provenance-bounds-audit
Aug 23, 2026
Merged

improvement(provenance): aggregate and attribute unrecorded durable reads#7017
icecrasher321 merged 1 commit into
stagingfrom
provenance-bounds-audit

Conversation

@icecrasher321

Copy link
Copy Markdown
Collaborator

Summary

  • Audited all four durable provenance surfaces (table-row, workspace-file, knowledge, memory) end to end on latest staging. The fail-open-on-absence policy is sound: work bounds over-approximate rather than drop provenance, model egress stays fail-closed, and absence reads are compensated by an audit trail. This PR closes the places where that compensating control was incomplete — zero behavior changes to any read or write path; every read that proceeded before still proceeds, every refusal still refuses.
  • Knowledge: fail-open reads produced one error log line per record and no audit rows (the per-record import knows no workspace, and the audit entry is skipped when it can't name one). Both importers now count unrecorded records and report once per read with workspaceId, actorUserId, and affectedCount — the same shape memory and tables already ship. Search reports once across chunks + rendered metadata, and only when the registry didn't latch; fault returns (row-missing/content-mismatch) stay silent because those reads fail closed.
  • Memory: the one silent local degrade — hash-bound overflow or unnormalizable entries turning an exact write unknown — now logs its cause at error where it's decided, matching the table writer. Incoming unknown stays silent (its producer already reported).
  • Memory contract: GET /api/memory limit gains .max(1000) per the tables convention. Internal-auth route; no caller in the repo passes a limit at all.
  • Workspace files: unrecorded-read audit rows carry the acting user where the caller already holds one (copilot vfs, agent/mothership handlers, provider attachment filter); elsewhere — including workspace-API-key principals with no user — the actor stays null, which the report type has always permitted.
  • Docs: the file sidecar comment catches up with the three-status absence/taint storage, and the mounted-file scanner documents why scan-overflow is a taint while the registry scan over-approximates.

Deliberately not touched (audit-confirmed accepted limitations): the fail-open default and enforcement env, the memory whole-array hash binding (follow-up with its own migration review), exact-empty certification of non-runtime writes, binary-output taint, the <8-char literal floor, and the envelope bounds. No schema changes, no migrations, no new incompleteness reasons or causes.

Type of Change

  • Improvement (observability; no behavior change)

Testing

2,313 tests green across every affected suite (knowledge, memory, uploads/workspace, copilot handlers/request, providers, agent/mothership handlers, api/memory, api/knowledge). New tests pin: one aggregated knowledge report per read with workspace/actor/count and none on fault or enforced paths; the search importer returning its count instead of reporting; the memory degrade log firing only for local degradation; the limit ceiling; the actor flowing into (and defaulting to null on) file audit rows. bun run type-check clean, bun run lint clean, all 33 audits pass including check:api-validation:strict.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…eads

Fail-open on unrecorded durable provenance rests on one compensating
control: the audit entry telling the people who own the secrets that a
read proceeded unvouched. An audit of all four surfaces found the
control incomplete in exactly the places this closes, and confirmed the
policy itself sound — so nothing here changes what any read or write
does, only what gets recorded about it.

Knowledge was the one surface with no audit trail at all: the
per-record import reports without a workspace, and the report skips the
audit row when it cannot name one, so fail-open knowledge reads emitted
one error log line per record and zero audit entries. Both importers
now count unrecorded records while the surface is open and report once
per read with the workspace, actor, and count — the shape memory and
tables already use. The search read reports once across chunks and
rendered metadata, and only when the registry did not latch, since a
latched read never reaches a model. Fault returns stay silent; those
reads fail closed.

Memory had the one silent local degrade: a record whose canonical hash
outgrows its bounds, or whose entries fail normalization, was stored
unknown with nothing logged anywhere — the table writer logs its
equivalent. The binding now logs the cause at error where it is
decided. An incoming unknown stays silent; its producer already
reported.

The memory list contract gains the page ceiling every other list
already has (max 1000, matching the table convention); no caller in
the repo passes a limit at all, and the route is internal-auth only.

Workspace-file audit rows now carry the acting user where the caller
already holds one — copilot vfs, the agent and mothership handlers,
and the provider attachment filter. Everywhere else, including
principals with no user to name, the actor stays null, which the
report type has always permitted.

Two comments catch up with the code: the file sidecar stores three
statuses since the absence/taint split, and the mounted-file scanner's
scan-overflow-to-taint is deliberate where the registry scan
over-approximates — that scan only narrows an already-sound candidate
set, while this one decides whether egress redaction would suffice for
bytes the same matcher just failed on.
@vercel

vercel Bot commented Aug 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 23, 2026 8:01pm

Request Review

@cursor

cursor Bot commented Aug 23, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Touches secret-provenance audit and import paths across knowledge, memory, and workspace files. Read/write allow/deny behavior is unchanged, but incorrect reporting could hide or mis-attribute fail-open reads.

Overview
Improves the compensating audit trail for fail-open unrecorded durable secret provenance. Allow/deny behavior is unchanged: fail-open reads still proceed, fail-closed refusals still refuse.

Knowledge now counts unrecorded documents/chunks and emits one reportUnrecordedDurableProvenance per read with workspaceId, actorUserId, and affectedCount (search folds chunks + rendered metadata into that same report). Per-record imports suppress their own reports. Fault/enforced paths stay silent.

Workspace files pass the acting user into unrecorded-read reports from copilot VFS, agent/mothership handlers, and provider attachment filtering; unnamed principals stay null.

Memory logs the local exact→unknown degrade (hash overflow or unnormalizable entries) at write time. GET /api/memory limit is capped at 1000. Docs comments clarify sidecar status vs reader classification and mounted-file scan overflow as taint.

Reviewed by Cursor Bugbot for commit f0b531d. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves durable-secret provenance observability without changing the existing fail-open and fail-closed read decisions.

  • Aggregates unrecorded knowledge provenance into workspace- and actor-attributed reports.
  • Adds acting-user attribution to workspace-file provenance reports where available.
  • Logs locally degraded memory provenance and caps memory list requests at 1,000 records.
  • Clarifies mounted-file and workspace-file provenance behavior with updated comments and tests.

Confidence Score: 5/5

The PR appears safe to merge, with the changed reporting and attribution paths preserving the existing provenance enforcement behavior.

The aggregate reports are emitted on successful fail-open reads, while faulted or incomplete registries continue to prevent unsafe provenance-bearing content from reaching model input; no actionable regression remains.

Important Files Changed

Filename Overview
apps/sim/lib/knowledge/secret-provenance.ts Suppresses per-record knowledge reports, returns aggregate counts for search, and emits one attributed persisted-read report after successful imports.
apps/sim/lib/knowledge/application/search.ts Combines unknown chunk and rendered-document metadata counts into one report while preserving fail-closed behavior for incomplete registries.
apps/sim/lib/uploads/contexts/workspace/workspace-file-secret-provenance.ts Threads optional acting-user identity through unrecorded workspace-file reporting without changing classification decisions.
apps/sim/lib/memory/secret-provenance.ts Adds an error log when exact incoming memory provenance degrades locally during hash binding or entry normalization.
apps/sim/lib/api/contracts/memory.ts Adds the documented maximum of 1,000 records to the memory-list query contract.
apps/sim/providers/index.ts Supplies the provider request user as the audit actor when filtering model-facing workspace-file attachments.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Durable knowledge, memory, or file read] --> B{Provenance status}
  B -->|Exact| C[Import provenance]
  B -->|Unrecorded and unenforced| D[Proceed fail-open]
  D --> E[Aggregate affected records]
  E --> F[Report workspace and acting user]
  B -->|Unknown fault or enforced| G[Latch registry or refuse]
  G --> H[Prevent unsafe model egress]
Loading

Reviews (1): Last reviewed commit: "improvement(provenance): aggregate and a..." | Re-trigger Greptile

@icecrasher321
icecrasher321 merged commit 9cecf0b into staging Aug 23, 2026
30 checks passed
@icecrasher321
icecrasher321 deleted the provenance-bounds-audit branch August 23, 2026 20:08
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