Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ curl -H "Authorization: Bearer $TRAKRF_ACCESS_TOKEN" \

# Update — partial merge-patch per RFC 7396. Only fields in the body are
# changed; omitted fields are left unchanged. Send `null` to clear a
# nullable field; `{}` is a documented no-op.
# nullable field; `{}` is a documented no-op against settable fields (it still advances `updated_at`).
curl -X PATCH "$BASE_URL/api/v1/assets/$ASSET_ID" \
-H "Authorization: Bearer $TRAKRF_ACCESS_TOKEN" \
-H "Content-Type: application/merge-patch+json" \
Expand Down
142 changes: 142 additions & 0 deletions superpowers/plans/2026-05-30-tra-892-docs-hygiene-bundle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# TRA-892 Docs-Hygiene Bundle Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Land four BB-fleet doc-hygiene corrections (3 wording one-liners + remove one stale backlog row) and groom the `contact.url` deferral in Linear.

**Architecture:** Docs-only edits in `trakrf/docs`. No spec/platform change — `info.contact.url` is already correct live. Verification is `pnpm build` + `pnpm lint` (no test suite for prose) plus targeted greps confirming each before/after.

**Tech Stack:** Docusaurus / Redocusaurus, pnpm, Markdown/MDX. Linear MCP for the grooming comment.

---

## File Structure

- Modify: `tests/blackbox/BB_PRE_KEY.md` — fixture-data wording (item 1)
- Modify: `docs/api/quickstart.mdx` — minimal-PATCH comment (item 2)
- Modify: `tests/blackbox/BB.md` — context-block version check (item 3)
- Modify: `tests/blackbox/BACKLOG.md` — remove obsolete deferral row (item 4a)
- Linear: comment on TRA-743 (item 4b)

---

### Task 1: `BB_PRE_KEY.md` — location is a scan projection, not an asset field

**Files:**

- Modify: `tests/blackbox/BB_PRE_KEY.md:47` and `:49`

- [ ] **Step 1: Edit line 47.** Replace:

```
- Every asset has `location_id` resolved from scan history — no asset on this fixture reads as `location_id: null`.
```

with:

```
- Every asset has a resolvable current location, but location is **not** a field on the asset object — it is resolved from scan history via the asset-locations report (`GET /api/v1/reports/asset-locations`) and per-asset history (`GET /api/v1/assets/{asset_id}/history`), both gated `tracking:read`. No fixture asset reads as location-unknown.
```

- [ ] **Step 2: Reconcile line 49** so it does not re-imply a field on the asset. Replace:

```
**Scans:** populated. Each org carries ~25 `asset_scans` per asset over a 90-day window (~675 per org), and the materialized `location_id` on every asset reflects the most-recent scan.
```

with:

```
**Scans:** populated. Each org carries ~25 `asset_scans` per asset over a 90-day window (~675 per org), and the current location reported for every asset (via the scan-data endpoints above) reflects its most-recent scan.
```

(Leave the rest of line 49 — the `tracking:read` sentence — unchanged.)

- [ ] **Step 3: Verify.** Run: `grep -n "location_id\` resolved\|materialized \`location_id\`" tests/blackbox/BB_PRE_KEY.md`
Expected: no matches (both imprecise phrasings gone).

---

### Task 2: `quickstart.mdx` — `{}` no-op qualifier

**Files:**

- Modify: `docs/api/quickstart.mdx:146`

- [ ] **Step 1: Edit line 146.** Replace:

```
# nullable field; `{}` is a documented no-op.
```

with:

```
# nullable field; `{}` is a documented no-op against settable fields (it still advances `updated_at`).
```

- [ ] **Step 2: Verify.** Run: `grep -n "documented no-op" docs/api/quickstart.mdx`
Expected: the line now contains "against settable fields (it still advances `updated_at`)".

---

### Task 3: `BB.md` — point version check at the app origin

**Files:**

- Modify: `tests/blackbox/BB.md:209`

- [ ] **Step 1: Edit line 209.** Replace:

```
- Spec/build version — fetch `$API_TEST_DOCS_URL/health.json` and record what it returns. If `/health.json` 404s, that's a finding; record what you did get.
```

with:

```
- Spec/build version — fetch `$API_TEST_APP_URL/health.json` (the app origin carries `version` + `spec_refreshed_at`; the docs origin's `/health.json` carries only the docs build stamp). Record what it returns. If `/health.json` 404s, that's a finding; record what you did get.
```

- [ ] **Step 2: Verify.** Run: `grep -n "Spec/build version" tests/blackbox/BB.md`
Expected: line now references `$API_TEST_APP_URL/health.json`.

---

### Task 4: `BACKLOG.md` — remove the obsolete `contact.url` deferral row

**Files:**

- Modify: `tests/blackbox/BACKLOG.md:47`

- [ ] **Step 1: Delete the entire table row** beginning `| Restore \`info.contact.url\` on OpenAPI spec` (line 47). Remove the whole line; leave the table header (41-42) and the three preceding rows (43-46) intact.

- [ ] **Step 2: Verify.** Run: `grep -n "info.contact.url" tests/blackbox/BACKLOG.md`
Expected: no matches. Run: `grep -c "^| " tests/blackbox/BACKLOG.md` and confirm the deferred-work table dropped by exactly one row.

---

### Task 5: Build + lint

- [ ] **Step 1:** Run: `pnpm build` Expected: success (no spec change; Redocusaurus fetches live spec).
- [ ] **Step 2:** Run: `pnpm lint` Expected: pass.

---

### Task 6: Commit + groom Linear

- [ ] **Step 1: Commit** the four file edits:

```bash
git add tests/blackbox/BB_PRE_KEY.md docs/api/quickstart.mdx tests/blackbox/BB.md tests/blackbox/BACKLOG.md
git commit -m "docs(api): TRA-892 BB-fleet hygiene — location-projection wording, PATCH no-op qualifier, BB version-check origin, retire contact.url deferral"
```

- [ ] **Step 2: Groom TRA-743 (already Done).** Add a Linear comment recording that `info.contact.url` was restored by design (TRA-882, Stripe pattern `https://trakrf.id`), so the `BACKLOG.md` "restore when a helpdesk lands" deferral has been removed as obsolete. No state change.

---

### Task 7: Push + PR (hold for approval before merge)

- [ ] **Step 1:** Push branch `docs/tra-892-docs-bundle`.
- [ ] **Step 2:** Open PR with the spec/plan link and the four-item summary. **Do not merge** — hold for user approval.
78 changes: 78 additions & 0 deletions superpowers/specs/2026-05-30-tra-892-docs-hygiene-bundle-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# TRA-892 — Docs-hygiene bundle: 3 one-line API-docs fixes + groom the `contact.url` deferral

**Date:** 2026-05-30
**Ticket:** TRA-892
**Type:** Docs-only PR (4 wording/backlog edits) + one Linear grooming comment

## Problem

The 2.6.1 black-box fleet (runs bb-261/262/263, svc `v1.1.1-165-g8ca09556`) surfaced four
documentation-hygiene items. **None gate the prod launch** — zero service/contract defects
were found. Each is a one-line wording correction or backlog grooming, safe to land any time.

## Prerequisite verification (done before writing)

Verified each claim against the live preview (`app.preview.trakrf.id`) and the current docs:

| Claim to verify | Finding | Consequence |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `AssetView` has no `location_id` field | Confirmed — current location is exposed only on `GET /reports/asset-locations` and `GET /assets/{id}/history` (`tracking:read`); `resource-identifiers.md` already states this correctly | Fix only the BB onboarding-wrapper shorthand (item 1) |
| Empty `PATCH {}` still advances `updated_at` | Confirmed by ticket's live evidence (200, `updated_at` drift); `quickstart.mdx:167` already documents the always-advance behavior in full | Add a one-line qualifier at the compressed mention `quickstart.mdx:145-146` (item 2) |
| Docs-origin `/health.json` lacks API/spec version | Confirmed — docs origin returns only the docs build stamp; `app` origin `/health.json` carries `version` + `spec_refreshed_at` | Point BB's version check at the app origin (item 3) |
| `info.contact.url` restored by design | Confirmed — live spec serves `info.contact.url: https://trakrf.id` (Stripe pattern: marketing root + `[email protected]`), restored via platform TRA-882 (PR #440) | The `BACKLOG.md` "restore the URL when a helpdesk lands" deferral is now obsolete (item 4) |

## Scope — four edits

### Item 1 — `tests/blackbox/BB_PRE_KEY.md` (fixture-data section)

`:47` currently reads as if `location_id` is a field on the asset object. Reword to state the
current location is resolved from scan history via the asset-locations report / history
endpoints, **not a field on the asset object**. Also reconcile `:49`'s parallel
"materialized `location_id` on every asset" phrasing so the doc stays internally consistent
after the item-1 fix (otherwise the two lines contradict). Both are minimal; the determinism
promise (every fixture asset has a resolvable current location) is preserved, only the
"it's a field" implication is removed.

### Item 2 — `docs/api/quickstart.mdx` (§ minimal PATCH)

`:145-146` compresses "`{}` is a documented no-op" too far. Reword to "a documented no-op
**against settable fields** (it still advances `updated_at`)". Chosen over "link to the design
note" because the same code block's prose at `:167` already deep-links
`design-notes#updated_at-is-an-optimistic-concurrency-token-on-patch`; the inline qualifier
closes the gap where a reader stops at the comment.

### Item 3 — `tests/blackbox/BB.md` (context-block version check)

`:209` tells the BB harness to fetch the spec/build version from `$API_TEST_DOCS_URL/health.json`,
which carries only the docs build stamp. Repoint it at `$API_TEST_APP_URL/health.json` (the
authoritative `version` + `spec_refreshed_at` surface) and note that the docs origin only
carries the docs build stamp, so the cohort stops filing "version missing" where-to-look nits.
Chosen over surfacing the API/spec version on the docs host — that is an infra/build change
outside doc-hygiene scope, and the ticket explicitly offers the BB.md correction as the
alternative.

### Item 4 — groom the `contact.url` deferral

TRA-743 (which removed `info.contact.url`) is **already Done**; the URL has since been restored
by design (TRA-882). So "close as resolved" reduces to grooming the residue:

- **Docs:** remove the now-stale `tests/blackbox/BACKLOG.md:47` row ("Restore `info.contact.url`
… when a helpdesk lands"). The deferred work is done — keeping the row would advertise a
removal that no longer reflects reality.
- **Linear:** add a comment to TRA-743 recording the course reversal (URL restored by design,
Stripe pattern, `https://trakrf.id`) and that the BACKLOG deferral has been removed as obsolete.
No state change — the ticket is already Done.

## Out of scope

- Surfacing API/spec version on the docs host (item 3's other option) — infra/build change.
- Any platform/spec change — `info.contact.url` is already correct on the live spec; no paired
platform edit is needed for any item.
- Touching `tests/blackbox/.env.local` — already re-keyed this session, unrelated.

## Verification

- `pnpm build` and `pnpm lint` pass (Redocusaurus fetches the live spec at build time; no spec
change here, so the build is unaffected).
- The three doc edits are wording-only; the BACKLOG edit removes one table row.
- TRA-743 grooming comment posted.
11 changes: 4 additions & 7 deletions tests/blackbox/BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ Test-org artifact states that BB cycles will observe but should not flag as serv

Items with real fixes that cost-benefit deliberately deferred. Each entry has an explicit trigger condition; the registry is groomed at post-launch milestones and whenever a trigger fires.

| Work | Origin | Trigger to revisit |
| ------------------------------------------------------------------------------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Bigint storage migration | TRA-720 | When cloud catches up to preview schema state AND customer volume hits the int32 ceiling (or enterprise data-residency requirements force it sooner). Retires the wire-vs-runtime int64 soft contract entirely; path-param maximum constraint (TRA-726) removed in same PR. |
| OpenAPI 3.1 migration | BB37 F5 context | When the generator ecosystem stabilizes 3.1 support across all targets we care about. Fixes `datamodel-codegen` nullable handling without per-generator workarounds; would let us drop the nullable design note from `/docs/api/design-notes`. |
| Path-param maximum constraint removal | BB37 F2 / TRA-726 | Same trigger as bigint storage migration (TRA-720). Documented in TRA-726 acceptance criteria. |
| Add `x-extensible-enum: true` annotations to `tag_type` discriminator and `OrgView.scopes` | BB39 F7 | Same trigger as the OpenAPI 3.1 migration above. 3.1's `const` keyword and improved discriminator support let us express closed/open splits cleanly; a standalone annotation now would carry forward, but the 3.1 migration retires the question. |
| Restore `info.contact.url` on OpenAPI spec | TRA-743 | When a helpdesk lands (Zendesk, Help Scout, Intercom, similar) or a marketing `/contact` page with topic routing ships. Add the URL back targeting that surface — GitHub pattern is a deep link with topic-routing parameter (`https://support.example.com/contact?tags=api`); Stripe pattern is a marketing root plus a dedicated team email. `docs.trakrf.id` was rejected as the target (env-leak from preview); `app.trakrf.id/api` was rejected (404/SPA shell, the bug BB42 surfaced). Current state is `info.contact.{name,email}` only — renders fine in Redoc and Swagger UI; adding URL later is non-breaking by OpenAPI 3.0 design. |
| Work | Origin | Trigger to revisit |
| ------------------------------------------------------------------------------------------ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| OpenAPI 3.1 migration | BB37 F5 context | When the generator ecosystem stabilizes 3.1 support across all targets we care about. Fixes `datamodel-codegen` nullable handling without per-generator workarounds; would let us drop the nullable design note from `/docs/api/design-notes`. |
| Add `x-extensible-enum: true` annotations to `tag_type` discriminator and `OrgView.scopes` | BB39 F7 | Same trigger as the OpenAPI 3.1 migration above. 3.1's `const` keyword and improved discriminator support let us express closed/open splits cleanly; a standalone annotation now would carry forward, but the 3.1 migration retires the question. |
2 changes: 1 addition & 1 deletion tests/blackbox/BB.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Begin FINDINGS.md with a context block recording:
- Environment URL (`API_TEST_APP_URL` value)
- Docs URL (`API_TEST_DOCS_URL` value)
- Track (mint-key or pre-key) and — for pre-key — the value of `$BB_ORG` and `$BB_ORG_ID`
- Spec/build version — fetch `$API_TEST_DOCS_URL/health.json` and record what it returns. If `/health.json` 404s, that's a finding; record what you did get.
- Spec/build version — fetch `$API_TEST_APP_URL/health.json` (the app origin carries `version` + `spec_refreshed_at`; the docs origin's `/health.json` carries only the docs build stamp). Record what it returns. If `/health.json` 404s, that's a finding; record what you did get.
- HTTP client(s) used in the exploratory pass (curl, Python `requests`, Node `fetch`, generated TypeScript client, etc.)
- Codegen tool(s) and version(s) used in step 10 — list each separately
- Date and time of the run (UTC)
Expand Down
Loading
Loading