REUSE-WP-0019-T04: reuse telemetry store and recording
Some checks failed
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 10s
ci / validate-registry (push) Has been cancelled
Build and Publish Container Image / build-and-push (push) Successful in 1m16s

Implements the hub side of the shared reuse-event schema (already drafted
in WP-0018-T01, schemas/reuse-event.schema.json): a SQLite reuse_events
table, POST /v1/reuse-events (token-auth), GET /v1/reuse-events?capability_id=
(read-only).

reuse_surface/plan_check.py: refactored record_outcome around a new
shared post_or_fallback_reuse_event() helper -- tries the hub first, falls
back to the local JSONL only on failure/unreachability, never both. New
record_manual_reuse_event() backs a new CLI command, reuse-surface
record-reuse, for retroactive facts recorded outside plan-check.

Privacy/scope (repo slugs and capability ids only, no code, no secrets) is
enforced structurally via the schema's additionalProperties: false, not
just by convention.

21 new pytest cases, 145 total pass. Live-verified against a real running
hub instance: POST/GET /v1/reuse-events directly, record-reuse and
plan-check --record-outcome both posting successfully to the hub, and --
after actually killing the hub process -- confirmed the fallback path
writes correctly to the local JSONL instead of erroring.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-07 22:32:19 +02:00
parent 2fcc91f2aa
commit d181043717
12 changed files with 562 additions and 32 deletions

View file

@ -267,10 +267,51 @@ unconfigured secret is `503` (fails closed, not open).
**Response `502`:** Recompose failed (stale is deliberately left set so the
next check reports the failure honestly, not silently).
Org-level webhook rollout (single config covering all repos, T03) and the
Forgejo Actions scheduled fallback for when webhooks are unavailable are
separate, deployment-side follow-ups — this section covers the receiver
contract only.
Org-level webhook rollout (single config covering all repos) and the
Forgejo Actions scheduled fallback both shipped in T03: the org webhook is
live on `coulomb` (id `1`, push events only), and
`.forgejo/workflows/recompose-fallback.yaml` in this repo calls
`POST /v1/federated/compose` on a 6-hour cron as a backstop.
### 5.10 `POST /v1/reuse-events`
Records one reuse telemetry fact (REUSE-WP-0019-T04). **Auth required.**
Body validated against `schemas/reuse-event.schema.json` — the same schema
`plan_check.py`'s local JSONL fallback uses, so a fact never differs in
shape depending on where it landed.
```json
{
"ts": "2026-07-08T00:00:00Z",
"consumer_repo": "some-repo",
"capability_id": "capability.infotech.issue-tracking",
"verdict": "reuse",
"outcome": "reused",
"source": "plan-check"
}
```
`capability_id`/`outcome` may be `null` (e.g. a `new` verdict with no
existing capability). `source` is one of `plan-check`, `manual`, `hub`.
`additionalProperties: false` — no code, no secrets, repo slugs and
capability ids only (privacy/scope constraint).
**Response `201`:** the recorded event.
**Response `400`:** schema validation failed.
**Response `401`:** missing/invalid bearer token.
### 5.11 `GET /v1/reuse-events`
Lists recorded reuse events, oldest first. No auth required (read-only,
same posture as `GET /v1/federated`).
Query parameters:
| Param | Default | Meaning |
|---|---|---|
| `capability_id` | (none) | Filter to one capability |
**Response `200`:** `{"count": N, "events": [...]}`.
---