Skip to content

fix: reconcile denylist key contract#29

Merged
isuttell merged 5 commits into
mainfrom
agents/denylist-key-contract
May 23, 2026
Merged

fix: reconcile denylist key contract#29
isuttell merged 5 commits into
mainfrom
agents/denylist-key-contract

Conversation

@isuttell

@isuttell isuttell commented May 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Reconciles the MVP denylist implementation with ADR 0057 so deletion and cleanup write the same keys that content reads. This keeps generic public 404 behavior while preserving the current direct signed content URL lifetime.

Changes

  • Change content denylist reads from artifact:* / revision:* / unwritten content-token:* to ad:* / rd:*, with optional wsd:* and ald:* reads only when token payload IDs exist.
  • Change api artifact denylist writes to ad:{artifactId} with diagnostic JSON and the current max signed content-token TTL.
  • Add focused tests for delete, cleanup, dry-run cleanup, optional token IDs, and generic denylisted 404 behavior.
  • Update ADR 0057 and project status to document the MVP-narrowed behavior and remaining backlog.

Risk: MEDIUM

  • Areas touched: api denylist writes, content denylist reads, worker tests, ADR/status docs.
  • Security: strengthens deletion/cleanup invalidation by aligning read/write keys; keeps public errors generic.
  • Performance: same KV read class; optional workspace/access-link reads only occur when token payload carries those IDs.
  • Breaking: no public API contract break; hosted smoke scripts still query old artifact:* keys and should be updated in a separate scoped change before using smoke as the denial-key assertion.

Test plan

  • pnpm turbo run test --filter=@agent-paste/content --filter=@agent-paste/api
  • pnpm turbo run test --filter=@agent-paste/api
  • pnpm turbo run lint typecheck --filter=@agent-paste/api
  • pnpm verify
  • pre-push hook focused API/content tests

CodeRabbit notes

  • Iteration 1 found one trivial actionable test coverage issue for API delete/cleanup response contracts and dry-run cleanup denylist writes.
  • Addressed in 070ddcf test: cover denylist cleanup contracts.
  • Iteration 2: coderabbit review --agent --base main completed with 0 findings.

Summary by CodeRabbit

  • Tests

    • Added coverage for artifact denylist behavior across admin and content flows: delete, cleanup (dry run and real), and token variations.
  • Behavior

    • Denylist keys/use updated (new key namespace) and denylist writes use structured deletion metadata with an extended TTL; signed-token validation tightened and denylist checks now conditionally include workspace and access-link IDs.
  • Documentation

    • ADR and project status updated to reflect key namespace, TTL, and read/write order.

Review Change Stack

@isuttell isuttell temporarily deployed to pr-preview-29 May 23, 2026 20:06 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d8d443cc-6ff4-482b-9743-5b9cf1926c09

📥 Commits

Reviewing files that changed from the base of the PR and between 79c2a6f and 53d477e.

📒 Files selected for processing (2)
  • docs/adr/0057-kv-denylist-namespace-keys-and-write-order.md
  • docs/ops/project-status.md

Walkthrough

This PR implements the finalized KV denylist key namespace per ADR 0057. The content service token payload now includes an optional workspace_id field and denylist reads derive keys from the token payload (ad: and rd: always, wsd: and ald: conditionally) rather than three fixed keys. The API denylist write behavior switches from artifact: prefix to ad: prefix with JSON payloads containing deletion reason and timestamp. Tests, scripts, and documentation are updated to reflect these changes. TTL aligns to the maximum signed content-token lifetime (90 days).

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ContentWorker
  participant DENYLIST
  Client->>ContentWorker: Request signed content with token
  ContentWorker->>ContentWorker: verify token -> payload
  ContentWorker->>ContentWorker: denylistKeysForPayload(payload)
  ContentWorker->>DENYLIST: Promise.all([get(ad:...), get(rd:...), maybe get(wsd:...), maybe get(ald:...)])
  alt any denylist entry present
    DENYLIST-->>ContentWorker: non-null
    ContentWorker-->>Client: 404 not_found
  else all null
    DENYLIST-->>ContentWorker: nulls
    ContentWorker-->>Client: 200 content
  end
Loading

Possibly related PRs

  • zaks-io/agent-paste#8: Touches artifact delete/cleanup flows and denylist assertions; may overlap where denylist keys are read or written.
  • zaks-io/agent-paste#4: Also modifies artifact delete path and local server denylist writes; changes could conflict with denyArtifact/key namespace updates.

"🐰 Along the ad: lane I hop,
Keys rewritten, no more slop,
Workspace, access, artifact aligned,
Ninety days mark the revoke assigned,
Tiny paws, tidy change, and onward I hop!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: reconcile denylist key contract' clearly and concisely summarizes the main change: aligning the denylist key formats used across the codebase (read/write consistency in ADR 0057 implementation).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agents/denylist-key-contract

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/adr/0057-kv-denylist-namespace-keys-and-write-order.md`:
- Line 29: Update the ADR so the TTL policy and the stated consistency window
agree: pick a single contract (either 90-day max TTL for denylist entries or a
15-minute accepted consistency window) and update the contradictions
accordingly; specifically edit the paragraph starting "Entries must live at
least as long as the longest content-gateway token..." and the sentence that
currently states a "15-minute accepted consistency window" so they reference the
same TTL/consistency semantics (e.g., clarify that denylist entries use a 90-day
max_ttl_seconds but the operational accepted consistency window for revocation
is 15 minutes for cache propagation, or change both to reflect a unified
short-lived content-token TTL), ensuring both phrases and any references to ADR
0056 remain consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a2534a73-9a44-45f9-a6d8-813857b2be42

📥 Commits

Reviewing files that changed from the base of the PR and between 481531d and 070ddcf.

📒 Files selected for processing (7)
  • apps/api/src/index.test.ts
  • apps/api/src/index.ts
  • apps/content/src/error-envelope.test.ts
  • apps/content/src/index.test.ts
  • apps/content/src/index.ts
  • docs/adr/0057-kv-denylist-namespace-keys-and-write-order.md
  • docs/ops/project-status.md

Comment thread docs/adr/0057-kv-denylist-namespace-keys-and-write-order.md
@isuttell isuttell mentioned this pull request May 23, 2026
6 tasks
@isuttell isuttell temporarily deployed to pr-preview-29 May 23, 2026 20:42 — with GitHub Actions Inactive
@isuttell isuttell temporarily deployed to pr-preview-29 May 23, 2026 21:01 — with GitHub Actions Inactive
@isuttell isuttell merged commit 00fd36b into main May 23, 2026
4 checks passed
@github-actions

Copy link
Copy Markdown

agent-paste PR preview resources were cleaned up. The pr-preview-${context.issue.number} environment is left in place; remove it from the GitHub UI if desired.

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