Skip to content

docs(content-drive): Status filter design (plan, research, data model, contract) (#37066) - #37171

Merged
zJaaal merged 3 commits into
issue-37066-content-drive-status-filterfrom
issue-37066-content-drive-status-filter-plan
Aug 24, 2026
Merged

docs(content-drive): Status filter design (plan, research, data model, contract) (#37066)#37171
zJaaal merged 3 commits into
issue-37066-content-drive-status-filterfrom
issue-37066-content-drive-status-filter-plan

Conversation

@zJaaal

@zJaaal zJaaal commented Aug 24, 2026

Copy link
Copy Markdown
Member

Spec-Kit PR 2 of a stack (stack #37172). Based on #37170 (the spec), so the diff here is only the design layer. Review #37170 first.

The stack

# Branch Base Carries
1 issue-37066-content-drive-status-filter main spec.md#37170
2 (this) issue-37066-content-drive-status-filter-plan branch 1 the design: plan, research, data model, contract
3 (not opened yet) this branch implementation + tests

⚠️ This PR also changes a repo-wide convention

a4e63f1 un-ignores specs/*/plan.md, research.md and quickstart.md. @nollymar — this touches the commit policy you set in #36416, so please weigh in.

Your original rule kept all five artifacts local on the "durable reference vs. process artifact" test, which was sound for the shape it was written for: one spec PR, one implementation PR. It predates this repo adopting GitHub's native stacked PRs (public preview 2026-07-30). Stacks add a middle layer whose entire purpose is reviewing the design — and gitignoring plan.md makes that layer a PR with nothing in it to review. That's how this surfaced.

tasks.md and checklists/ stay ignored: both are regenerated by their own command, and a merged task list that no longer matches what shipped is worse than no task list. .specify/CUSTOMIZATIONS.md is updated with the revised policy table and the reasoning. Happy to split this into its own PR against main if you'd rather the team decide it separately from a feature stack.

Proposed Changes

  • plan.md — the design: approach, Legacy Impact, Test Strategy, Constitution Check, ADR Alignment gate.
  • research.md — R1–R10, each verified against the code at e46da2b187 rather than taken from the issue text.
  • quickstart.md — build/test commands and the end-to-end validation walkthrough.
  • data-model.md — the ContentStatus enum and its column/index mapping, the status transport shape and validation rules, the BrowserQuery field, the frontend filter-bag entry.
  • contracts/drive-search-status.md — the status field on POST /api/v1/drive/search: accepted values, AND semantics with a per-combination result table, the showFolders side effect, the 400 on an unknown value.
  • .gitignore + .specify/CUSTOMIZATIONS.md — the convention change above.

Design decisions worth a reviewer's eye

1. All three predicates resolve in the database. ADR-0018 routes version-info flags (archived/deleted) to the DB and says structural criteria must never be re-routed to the index for speed. All three statuses are version-info flags:

Status SQL Index term
ARCHIVED cvi.deleted = true +deleted:true
UNPUBLISHED cvi.live_inode is null +live:false
LOCKED cvi.locked_by is not null +locked:true

The index terms exist only because BROWSE_API_HEURISTIC_TYPE=PURE_ES is a supported (non-default) configuration where the filter would otherwise silently no-op, returning a wider set than asked for. Under the default hybrid heuristic the SQL clauses apply with and without a keyword.

2. status is typed List<String>, not List<ContentStatus>. The AC asks for a 400 on an invalid value "consistent with how userSearchable rejects unknown keys", and that precedent is an explicit BadRequestException thrown in ContentDriveHelper. A typed field would route through Jackson's deserialization error instead, whose status mapping is less direct. The typed field is prettier; the deterministic error is worth more.

3. No schema or mapping change. deleted, live_inode and locked_by already exist on contentlet_version_info (postgres.sql:550-552), and locked is already indexed (ESMappingAPIImpl.java:527). Nothing here is rollback-unsafe.

The risk this design carries into PR 3

Two existing code paths already have an opinion about cvi.deleted, and both must learn about ARCHIVED or the filter breaks:

  • The global archived exclusion (BrowserAPIImpl:2006) would otherwise emit cvi.deleted = false alongside = true, so ARCHIVED would always return nothing.
  • Archive-target workflow steps (:1980) — appendWorkflowQuery owns cvi.deleted per branch when such a step is selected, so ARCHIVED needs the same treatment showArchived already gets. ContentDriveWorkflowArchiveStepTest is the regression guard.

With no status sent, every generated query stays byte-identical to today. See research.md R5.

Checklist

  • Tests — land in PR 3, written and confirmed failing first (Constitution Principle V). Full strategy in plan.md: unit for status parsing + the 400; integration for each status, each pair, all three, the empty default, PURE_ES parity and the workflow archive-step regression; Jest/Spectator for the chip, the store payload and the URL round-trip
  • Translations — four content-drive.status-filter.* keys, in PR 3
  • Security Implications Contemplated — the only input is a closed enum, validated against it and rejected with a 400, so it never reaches SQL as text. Permission filtering is untouched, so the filter grants no new visibility

Additional Info

/speckit-adr-context ran as the mandatory before_plan hook. ADR-0018 (proposed) governs and this design complies; ADR-0009 (accepted) constrains only the index terms, all core fields mapped identically under ES and OpenSearch; ADR-0020 surfaced but does not apply. No new ADR proposed — this adds a filter within an already-decided routing contract.

🤖 Generated with Claude Code

This PR fixes: #37066

This PR fixes: #37066

…37066)

Phase 1 design artifacts for the Status filter, stacked on the spec PR.

Carries only the two artifacts .specify/CUSTOMIZATIONS.md considers durable:
data-model.md (the ContentStatus enum, the `status` transport shape, the
filter-bag entry) and contracts/ (the `status` field on POST /api/v1/drive/search,
including the AND semantics and the 400 on an unknown value).

plan.md, research.md and quickstart.md stay local by design — the repo
gitignores them as process-only artifacts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Claude finished @zJaaal's task in 1m 44s —— View job


SDK Compatibility Review — PR #37171

  • Read docs/core/SDK_BREAKING_CHANGE_CATEGORIES.md
  • Reviewed the full set of changed files for this PR
  • Checked against every category (G-1/G-2/G-3, R-1, U-1/U-2, H-1)
  • Conclusion reached

Result: No SDK-breaking change detected.

This PR is documentation-only — it's Spec-Kit PR 2 of 3 (per #37170/#37171), carrying design artifacts, not runtime code:

  • .gitignore, .specify/CUSTOMIZATIONS.md — process/tooling config
  • specs/37066-content-drive-status-filter/{data-model.md, contracts/drive-search-status.md, plan.md, quickstart.md, research.md} — markdown design docs describing a future status filter contract (POST /api/v1/drive/search) that has not been implemented yet

None of these touch a live wire-format surface: no GraphQL schema/resolver changes reachable via graphql.page/graphql.content, no changes to /api/v1/nav, /api/v1/content, or /api/v1/page/* response shapes (the status field described in contracts/drive-search-status.md doesn't exist on any endpoint yet — it's a proposal), no UVE postMessage protocol changes, and no changes to SdkVersionWebInterceptor/sdk-compatibility.ts. The actual implementation (and any real compatibility risk) lands in PR 3 of the stack, not here.

No comment or label added, per instructions (only acts when a breaking change is found).

zJaaal and others added 2 commits August 24, 2026 11:07
Restores stock Spec-Kit behavior for the three artifacts a reviewer needs to
judge a design. Only tasks.md and checklists/ stay gitignored.

The original policy in #36416 kept all five local on the "process artifact"
test. That predates this repo adopting GitHub's native stacked pull requests
(public preview 2026-07-30), which changes the calculation: the spec-driven
flow now lands as a stack whose middle layer exists purely to review the
design. Gitignoring plan.md makes that layer a PR with nothing to review.

tasks.md and checklists/ stay ignored — both are regenerated by their own
command, and a merged task list that no longer matches what was built is worse
than no task list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…37066)

Now trackable after the preceding gitignore change. These are the artifacts
/speckit-plan already generated for this feature; they were sitting on disk,
invisible to review.

- plan.md      design, Legacy Impact, Constitution Check, ADR Alignment gate
- research.md  R1-R10, each verified against the code rather than the issue text
- quickstart.md build/test commands and the end-to-end validation walkthrough

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@zJaaal zJaaal changed the title docs(content-drive): Status filter data model and API contract (#37066) docs(content-drive): Status filter design (plan, research, data model, contract) (#37066) Aug 24, 2026
@zJaaal
zJaaal merged commit 4c6f547 into issue-37066-content-drive-status-filter Aug 24, 2026
32 checks passed
@zJaaal
zJaaal deleted the issue-37066-content-drive-status-filter-plan branch August 24, 2026 14:09
@zJaaal

zJaaal commented Aug 24, 2026

Copy link
Copy Markdown
Member Author

Folded into #37170 rather than reviewed separately — GitHub marked this merged automatically once its commits fast-forwarded into the base branch.

The spec and its design artifacts are one reviewable unit, so splitting them across two PRs was overhead without a payoff. Everything that was here (plan.md, research.md, quickstart.md, data-model.md, contracts/, and the .gitignore convention change) is on #37170, unchanged. Review #37170; nothing is lost by ignoring this PR.

The stack is now #37170 (spec + design) → implementation, which is the two-PR shape CLAUDE.md describes anyway.

Analysis and comment by Claude (Claude Code), posted from @zJaaal's account.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Content Drive: Status filter (Archived, Unpublished, Locked) on drive search and in the toolbar

1 participant