Files
the-custodian/workplans/CUST-WP-0002-contribution-tracking-sbom.md
tegwick d96ed44c57 feat(maintenance): add stale-task cleanup scheme
- scripts/cleanup_stale_tasks.py: daily script that cancels open tasks
  in completed/archived workstreams; handles 307 redirects; emits a
  cleanup progress event summarising results
- Makefile: add cleanup-stale target (also suitable for cron)
- ADR-001: append Workstream Closure Protocol section — mandatory closure
  review before marking workstream completed, with task classification
  table (done/cancelled/carry-forward) and Closure Review file format
- WP-0002 + WP-0005: append Closure Review sections documenting the
  2026-03-02 cleanup run (26 stale DB rows cancelled — all were legacy
  pre-ADR-001 DB-first records; file status was already done)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 00:32:35 +01:00

325 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: CUST-WP-0002
type: workplan
title: "State Hub v0.3 — Contribution Tracking & SBOM"
domain: custodian
status: completed
owner: custodian
topic_slug: custodian
state_hub_workstream_id: 2446400d-6d01-4679-a314-92af0601c608
created: "2026-02-26"
updated: "2026-02-28"
---
# State Hub v0.3 — Contribution Tracking & SBOM
## Summary
Establish the custodian as the central authority for cross-repo upstream
contribution management (bug reports, feature requests, extension points,
upstream PRs) and software supply-chain transparency (SBOM aggregation,
licence governance).
## Context
Three interconnected layers:
- **Layer 1 — Convention & Canon**: define contrib/ directory structure and
artifact types (BR, FR, EP, UPR) in markdown with typed YAML frontmatter.
- **Layer 2 — Schema & API**: DB tables for contributions, repos (deferred
to v0.5), and SBOM entries; FastAPI routers.
- **Layer 3 — MCP Tools & Dashboard**: tracking tools and Observable pages.
## Dependencies
- Depends on: `dynamic-domains-multi-repo` (v0.5, CUST-WP-0005).
Four tasks in this workplan (P2.2, P2.4, P3.2, P4.1) are reduced in
scope because v0.5 supersedes their original designs:
- `managed_repos` table → done by v0.5 P2.1
- `/repos/` API router → done by v0.5 P2.2
- `register_repo` MCP tool → done by v0.5 P3.1
- Base registration workflow → done by v0.5 P2.3
- state_hub_dep_id: 2033172d-2462-4253-acb7-cb64c7432480
## Phase 1 — Convention & Canon
### P1.1 — Write canon/standards/contribution-convention_v0.1.md
```task
id: CUST-WP-0002-T01
state_hub_task_id: c2d7df02-5f37-4c02-a418-fe7ab0050edc
status: done
priority: high
```
Define the master contrib/ convention: directory layout, artifact types
(BR/FR/EP/UPR), frontmatter schema per type, ID schemes (EP-<DOMAIN>-NNN
for EPs; date-prefixed slug for others), status lifecycle, and
relationship to state-hub. Authoritative reference for other repos.
### P1.2 — Create contrib/ templates for BR, FR, EP, UPR
```task
id: CUST-WP-0002-T02
state_hub_task_id: 5ef89639-950c-4d57-9578-6d0211edc2df
status: done
priority: high
```
Four Markdown template files under `canon/standards/contrib-templates/`:
`br-template.md`, `fr-template.md`, `ep-template.md`, `upr-template.md`.
Each has typed YAML frontmatter matching the schema in P1.1 plus a guided
prose skeleton.
### P1.3 — Store Observable Framework TOC sidebar UPR as first artifact
```task
id: CUST-WP-0002-T03
state_hub_task_id: e8251873-647c-4a4b-b283-298260b19c22
status: done
priority: medium
```
Create `contrib/upstream-prs/2026-02-26--observablehq--framework--toc-sidebar-inject.md`
using the UPR template. Captures: summary of the `injectTocTop` utility,
motivation, link to local component, target upstream file, draft PR body.
Status: draft.
### P1.4 — Align Railiance EP convention docs with canon master spec
```task
id: CUST-WP-0002-T04
state_hub_task_id: 1c982457-de52-4fc1-a439-3bf3120bb5b6
status: done
priority: low
```
The staged-promotion-lifecycle workstream defines EP-RAIL-NNN IDs and
inline doc markers. Review and update so the Railiance convention is a
proper instance of the custodian master spec, not a parallel one.
## Phase 2 — Schema & API
### P2.1 — Design and implement contributions DB table + migration
```task
id: CUST-WP-0002-T05
state_hub_task_id: c41d71bd-dc88-4201-bd9a-3f8a4eae4910
status: done
priority: high
```
Add `contributions` table: id (UUID PK), type (enum: br|fr|ep|upr),
target_org, target_repo, slug, title, status (enum:
draft|submitted|acknowledged|accepted|rejected|merged|withdrawn),
body_path (relative path to .md file), related_topic_id (nullable FK),
related_workstream_id (nullable FK), submitted_at, resolved_at, notes,
created_at, updated_at. Alembic migration.
### P2.2 — sbom_entries table + migration (managed_repos deferred to v0.5)
```task
id: CUST-WP-0002-T06
state_hub_task_id: 28c9bd38-05d8-4466-bff3-3ba4e3957635
status: done
priority: high
```
SCOPE REDUCED — managed_repos superseded by v0.5 P2.1.
Do not create `managed_repos` here. After v0.5 P2.1 lands, add
`sbom_source` (text) and `last_sbom_at` (timestamp) columns to the
existing `managed_repos` table via an additive migration.
Then create `sbom_entries` table: id (UUID PK), repo_id (FK
managed_repos), package_name, package_version, ecosystem, license_spdx
(nullable), is_direct (bool), is_dev (bool), snapshot_at (timestamp —
new ingest replaces old entries for that repo), created_at.
Prerequisite: v0.5 P2.1 (managed_repos table) must be complete.
### P2.3 — Implement /contributions/ router (CRUD + status patch)
```task
id: CUST-WP-0002-T07
state_hub_task_id: ee1cd17c-6dbd-4321-bb72-4499147c4837
status: done
priority: high
```
FastAPI router: GET list (filter by type, status, target_repo), POST
create, GET by id, PATCH status (validates lifecycle transitions), soft
delete (sets status=withdrawn). Schemas: `ContributionCreate`,
`ContributionRead`, `ContributionStatusPatch`. Add
`contribution_counts` to `/state/summary`.
### P2.4 — Implement /sbom/ router (basic /repos/ endpoints implemented by v0.5)
```task
id: CUST-WP-0002-T08
state_hub_task_id: 25f7ab5c-69d8-41d7-a108-38380eb1f3a9
status: done
priority: high
```
SCOPE REDUCED — /repos/ superseded by v0.5 P2.2.
This task covers the `/sbom/` router only:
- `POST /sbom/ingest` — accept repo_slug + list of package entries;
replace existing snapshot for that repo.
- `GET /sbom/` — aggregated view across all repos, grouped by license_spdx.
- `GET /sbom/{repo_slug}/` — single-repo SBOM.
- `GET /sbom/report/licences/` — counts and repo lists per SPDX identifier,
flagging copyleft (GPL/AGPL/LGPL).
- Add `licence_risk_count` to `/state/summary`.
Prerequisite: v0.5 P2.1 (managed_repos) and P2.2 (sbom_entries) must
be complete.
### P2.5 — Write make ingest-sbom tooling (pyproject + package.json parsers)
```task
id: CUST-WP-0002-T09
state_hub_task_id: edcf9b02-8177-4abc-b133-d303cc7ea19d
status: done
priority: medium
```
`scripts/ingest_sbom.py`: parses `uv.lock` (Python deps with licence
metadata), `package-lock.json` / `yarn.lock` (Node deps); outputs
normalised list; POSTs to `/sbom/ingest/`. Makefile target:
`make ingest-sbom REPO=<slug>`. Composable into `make seed`.
## Phase 3 — MCP Tools & Dashboard
### P3.1 — New MCP tools: register_contribution, update_contribution_status, get_contributions
```task
id: CUST-WP-0002-T10
state_hub_task_id: 51b2999b-a9c7-4871-8ef8-f5c927ac2454
status: done
priority: high
```
- `register_contribution(type, target_org, target_repo, title, body_path,
related_workstream_id?, notes?)` → ContributionRead
- `update_contribution_status(contribution_id, status, notes?)` →
ContributionRead
- `get_contributions(type?, status?, target_repo?)` → list
- Add `state://contributions` resource.
### P3.2 — New MCP tools: ingest_sbom, get_licence_report (register_repo implemented by v0.5)
```task
id: CUST-WP-0002-T11
state_hub_task_id: 20c5c2ae-7758-42cc-885c-a886957e44c2
status: done
priority: high
```
SCOPE REDUCED — register_repo superseded by v0.5 P3.1.
- `ingest_sbom(repo_slug: str, lockfile_path: str)` — calls
`scripts/ingest_sbom.py`, POSTs result to `/sbom/ingest/`.
- `get_licence_report()` — returns licence groups with copyleft flag from
`/sbom/report/licences/`.
- Add resources: `state://sbom/aggregated`, `state://sbom/{repo_slug}`.
Prerequisite: v0.5 P3.1 (register_repo tool) and P2.4 (/sbom/ router)
must be complete.
### P3.3 — Dashboard: contributions.md page
```task
id: CUST-WP-0002-T12
state_hub_task_id: 1eb13411-b2da-4d0d-8fe2-e926d029c50f
status: done
priority: medium
```
New Observable Framework page. Layout: filter bar (type, status,
target_repo), status Kanban columns
(draft → submitted → acknowledged → accepted/rejected/merged), count KPIs
per type. Chart: contribution velocity over time (cumulative, same period
selector as decisions page). Apply `injectTocTop` for page-level KPI.
### P3.4 — Dashboard: sbom.md page
```task
id: CUST-WP-0002-T13
state_hub_task_id: 1267f313-1bf3-4059-8276-bfefcd9f6aed
status: done
priority: medium
```
New Observable Framework page. Aggregated dependency table: package,
version, licence, repos using it, direct/dev flags. Licence summary donut
chart (MIT vs Apache-2.0 vs GPL family vs other). Copyleft risk section
(red highlight for GPL/AGPL/LGPL in direct prod deps). Per-repo
drill-down accordion. Register in `observablehq.config.js`.
### P3.5 — Update index.md overview to surface contribution and SBOM health
```task
id: CUST-WP-0002-T14
state_hub_task_id: abab0022-d3a4-45ef-a7e1-e0e7c05d295f
status: done
priority: low
```
Add contribution counts KPI card (total, by type, any needing follow-up).
Add licence risk indicator (green if no copyleft in direct prod deps, red
otherwise). Uses `/state/summary` fields added in P2.3 and P2.4.
## Phase 4 — Repo Integration Tooling
### P4.1 — Add sbom_source prompt + ingest-sbom step to registration workflow (base workflow by v0.5)
```task
id: CUST-WP-0002-T15
state_hub_task_id: 47987720-23db-4465-861b-1f93bb1bb391
status: done
priority: low
```
SCOPE REDUCED — base registration workflow superseded by v0.5 P2.3.
SBOM-specific additions to the workflow:
1. Extend the `add-repo` command to prompt for `ecosystem` and
`sbom_source` (path or URL to lockfile).
2. Optionally run `make ingest-sbom REPO=<slug>` automatically at end of
registration.
3. Update `project_claude_md.template` to document the contrib/ convention,
SBOM MCP tools, and `make ingest-sbom` target.
Prerequisite: v0.5 P2.3 (updated registration workflow) must be complete.
---
## Closure Review — 2026-03-02
**Outcome:** All 15 tasks completed. No carry-forwards. No dropped tasks.
**Context:** This workplan was created DB-first on 2026-02-28, before ADR-001 was formalised. The workplan file correctly recorded all tasks as `status: done`, but the DB rows were never synced from the file — they remained in their initial `todo` state in the database. The daily stale-task cleanup script (`scripts/cleanup_stale_tasks.py`) detected these 15 stale DB rows and cancelled them on 2026-03-02. No actual work was lost: all deliverables in Phase 14 were shipped as part of State Hub v0.3.
### Completed (DB updated at delivery time; file status = done)
- CUST-WP-0002-T01 — Write canon/standards/contribution-convention_v0.1.md
- CUST-WP-0002-T02 — Create contrib/ templates for BR, FR, EP, UPR
- CUST-WP-0002-T03 — Store Observable Framework TOC sidebar UPR as first artifact
- CUST-WP-0002-T04 — Align Railiance EP convention docs with canon master spec
- CUST-WP-0002-T05 — Design and implement contributions DB table + migration
- CUST-WP-0002-T06 — sbom_entries table + migration
- CUST-WP-0002-T07 — Implement /contributions/ router (CRUD + status patch)
- CUST-WP-0002-T08 — Implement /sbom/ router
- CUST-WP-0002-T09 — Write make ingest-sbom tooling
- CUST-WP-0002-T10 — New MCP tools: register_contribution, update_contribution_status, get_contributions
- CUST-WP-0002-T11 — New MCP tools: ingest_sbom, get_licence_report
- CUST-WP-0002-T12 — Dashboard: contributions.md page
- CUST-WP-0002-T13 — Dashboard: sbom.md page
- CUST-WP-0002-T14 — Update index.md overview to surface contribution and SBOM health
- CUST-WP-0002-T15 — Add sbom_source prompt + ingest-sbom step to registration workflow
### Cancelled (DB records only — legacy stale rows, not real cancellations)
All 15 DB task rows were cancelled by the cleanup script. The workplan file was authoritative; the DB rows were artefacts of the pre-ADR-001 DB-first creation pattern. This does not reflect a change in work outcome.