BC5 readiness: forward-compat spec, briefs, parity lint#293
Conversation
Spec Change Impact
Checklist of SDKs needing updates:
|
There was a problem hiding this comment.
Pull request overview
Foundation work to prepare the SDK repo for BC5 readiness: additive Smithy/OpenAPI model updates, new repo-level spec/brief validation tooling, and regenerated multi-language SDK artifacts pinned to the updated API version.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Changes:
- Add BC5 forward-compat fields to the Smithy spec (notifications bubble-up fields, todo steps, todoset counts/URLs, person tagline) and regenerate OpenAPI + SDK model artifacts.
- Introduce repo lints/utilities: bucket↔flat parity check, API gap brief validator, and branch-aware BC3 drift reporting wired into
make check/make sync-status. - Add and validate API gap briefs + allowlist schema/docs, and add
make generateas a full regeneration aggregator.
Reviewed changes
Copilot reviewed 34 out of 50 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| typescript/src/generated/schema.d.ts | Generated TS schema typings updated for new BC5 fields + descriptions. |
| typescript/src/generated/openapi-stripped.json | Generated stripped OpenAPI updated (version + new schema fields/docs). |
| typescript/src/generated/metadata.json | Regeneration timestamp update. |
| typescript/src/client.ts | Bump TS SDK API_VERSION to 2026-05-01. |
| swift/Sources/Basecamp/Generated/Models/Todoset.swift | Generated Swift model updated with new todoset fields. |
| swift/Sources/Basecamp/Generated/Models/Todo.swift | Generated Swift model updated with embedded steps. |
| swift/Sources/Basecamp/Generated/Models/Person.swift | Generated Swift model updated with tagline. |
| swift/Sources/Basecamp/Generated/Models/Notification.swift | Generated Swift model updated with bubble-up fields. |
| swift/Sources/Basecamp/Generated/Models/GetMyNotificationsResponseContent.swift | Generated Swift response content updated with bubble-up collections. |
| swift/Sources/Basecamp/BasecampConfig.swift | Bump Swift SDK apiVersion to 2026-05-01. |
| spec/bucket-scoped-allowlist.txt | New allowlist for bucket-scoped list ops without flat counterparts. |
| spec/basecamp.smithy | Smithy service version bump + additive BC5 model fields. |
| spec/api-provenance.json | Provenance structure updated to track active branch + compatibility baseline. |
| scripts/validate-briefs.sh | Shell entrypoint for briefs validation (Ruby). |
| scripts/validate-briefs.rb | Ruby validator for brief frontmatter/body sections + allowlist schema checks. |
| scripts/report-bc3-drift.sh | New helper to report drift for an arbitrary BC3 baseline/branch/label. |
| scripts/check-bucket-flat-parity.sh | New lint to enforce bucket↔flat list-operation parity (with allowlist). |
| ruby/lib/basecamp/version.rb | Bump Ruby SDK API_VERSION to 2026-05-01. |
| ruby/lib/basecamp/generated/types.rb | Regenerated Ruby types with BC5 additive fields. |
| ruby/lib/basecamp/generated/metadata.json | Regeneration timestamp update. |
| python/src/basecamp/generated/types.py | Regenerated Python TypedDicts with BC5 additive fields. |
| python/src/basecamp/_version.py | Bump Python SDK API_VERSION to 2026-05-01. |
| openapi.json | Generated OpenAPI updated (version + new schema fields/docs). |
| kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Todoset.kt | Regenerated Kotlin model updated with new todoset fields. |
| kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Todo.kt | Regenerated Kotlin model updated with embedded steps. |
| kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/Person.kt | Regenerated Kotlin model updated with tagline. |
| kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/BasecampConfig.kt | Bump Kotlin SDK API_VERSION to 2026-05-01. |
| go/pkg/generated/client.gen.go | Regenerated Go client models with BC5 additive fields. |
| go/pkg/basecamp/version.go | Bump Go SDK APIVersion to 2026-05-01. |
| go/pkg/basecamp/api-provenance.json | Go copy of provenance updated to new structure. |
| briefs/api-gaps/todoset-completed-list-visibility.md | New API gap brief. |
| briefs/api-gaps/step-top-level.md | New API gap brief. |
| briefs/api-gaps/stack-doc-and-smithy.md | New API gap brief. |
| briefs/api-gaps/search-filter-additions.md | New API gap brief. |
| briefs/api-gaps/scratchpad.md | New API gap brief. |
| briefs/api-gaps/schema.json | New JSON schema for brief frontmatter. |
| briefs/api-gaps/rich-text-project-attachable.md | New API gap brief. |
| briefs/api-gaps/recording-bubbleupable-field.md | New API gap brief. |
| briefs/api-gaps/recordable-subtypes-doc.md | New API gap brief. |
| briefs/api-gaps/everything-aggregates.md | New API gap brief. |
| briefs/api-gaps/calendar.md | New API gap brief. |
| briefs/api-gaps/allowlist.yml | New allowlist for detector-classified routes that don’t require briefs. |
| briefs/api-gaps/allowlist-schema.json | JSON schema for the briefs allowlist format. |
| briefs/api-gaps/activity-timeline.md | New API gap brief. |
| briefs/api-gaps/README.md | Overview doc + table of briefs + validation instructions. |
| briefs/COORDINATION.md | Cross-team coordination doc for BC3 parity + SDK absorption lifecycle. |
| behavior-model.json | Behavior model updated for new Person.tagline JSON path. |
| Makefile | Add generate aggregator; wire new lints/validators into check; improve sync-status. |
| CONTRIBUTING.md | Document make generate, parity lint, and briefs workflow. |
| .gitignore | Ignore Kotlin .kotlin/ build artifacts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
6 issues found across 50 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/validate-briefs.rb">
<violation number="1" location="scripts/validate-briefs.rb:78">
P2: `status =~ Regexp.new(status_pattern)` will raise a `TypeError` if YAML frontmatter supplies a non-string value (e.g., `status: 123`). Guard with `status.is_a?(String)` before applying the regex match so the validator reports a clean error instead of crashing.</violation>
<violation number="2" location="scripts/validate-briefs.rb:144">
P2: Reading `allowlist-schema.json` without an existence check can crash the validator with `Errno::ENOENT` when allowlist exists but schema is missing.</violation>
</file>
<file name="briefs/api-gaps/schema.json">
<violation number="1" location="briefs/api-gaps/schema.json:7">
P2: Top-level `additionalProperties: true` lets unknown/misspelled frontmatter fields pass validation, reducing the effectiveness of `validate-briefs`.</violation>
</file>
<file name="scripts/check-bucket-flat-parity.sh">
<violation number="1" location="scripts/check-bucket-flat-parity.sh:18">
P2: Default file paths are CWD-relative, so running this script outside repo root can produce false failures or skip the allowlist. Resolve paths from the script/repo root before reading files.
(Based on your team's feedback about anchoring shell scripts to the repository root.) [FEEDBACK_USED]</violation>
<violation number="2" location="scripts/check-bucket-flat-parity.sh:56">
P2: Silencing `jq` failures with `2>/dev/null || true` means that if the OpenAPI file is invalid JSON or the filter expression fails, `CANDIDATES` becomes empty and the lint exits with "0 bucket-scoped list operations found" — a false pass. Let `jq` errors propagate (or detect the non-zero exit explicitly) so spec-level problems aren't masked.</violation>
</file>
<file name="briefs/COORDINATION.md">
<violation number="1" location="briefs/COORDINATION.md:5">
P3: The document references a non-existent local planning file path, so collaborators cannot access the stated source of truth.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
1e1c949 to
5bd407c
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 34 out of 50 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add optional fields to existing Smithy structures for BC5 read paths, keeping BC4 readers fully compatible. All additions are opt-in: absent fields are tolerated, present fields decode through the existing types. * Notification: bubble_up_url, bubble_up_at (eligibility-gated) * GetMyNotificationsOutput: bubble_ups, scheduled_bubble_ups; document current memories[] behavior pending BC team's back-compat decision * Person: tagline (alias of bio in BC5) * Todo: steps (reuses existing CardStep wire shape) * Todoset: todos_count, completed_loose_todos_count, todos_url, app_todos_url Restructure spec/api-provenance.json for parallel branch tracking — .bc3 keeps the active-branch baseline (now five), .compatibility.bc3-master records the BC4 baseline for compatibility tracking. Existing tooling (sync-spec-version, sync-api-version, Go provenance.go) reads the same .bc3 keys and works unchanged. Seed spec/bucket-scoped-allowlist.txt with the only existing bucket-only list endpoint (webhooks) for the new parity lint.
5bd407c to
63205bf
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 34 out of 50 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63205bfebc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…status
* make generate — single command to regenerate every machine-derived
artifact in the repo (Smithy, behavior model, URL routes, provenance,
per-language SDKs) in dependency order.
* make check-bucket-flat-parity — new lint that scans openapi.json for
GET /{accountId}/buckets/{bucketId}/<resource>(/...).json list
operations and verifies each has a flat counterpart at
/{accountId}/<resource>.json (or is justified in
spec/bucket-scoped-allowlist.txt). Cross-project SDK consumers
shouldn't have to walk every project to query account-wide data.
* make sync-status — reads .bc3.branch and reports drift for the active
branch (now five) and the compatibility branch (master) as two
clearly-labeled blocks via scripts/report-bc3-drift.sh, instead of
silently mixing them under HEAD.
* make validate-api-gaps target wired into make check (script lands in
the api-gaps registry commit).
The SDK is the client-side demand signal for BC3 API coverage. spec/api-gaps/
is a durable, schema-validated registry: each entry tracks one BC5
user-visible feature that ships without (or with incomplete) JSON API
coverage, paired with the BC3 parity plan that owns server-side delivery.
Status changes flow through git history, making the absorption journey
publicly auditable.
Initial registry (11 entries aligned with BC3 plan Phase 3 deliverables):
* calendar — show/update only
* scratchpad — URL path deferred by BC3 plan
* step-top-level — doc-only addition (existing partial)
* everything-aggregates — Phase 3c flat top-level recording listings (~22)
* activity-timeline — /activity (global) + /projects/:id/timeline
* recordable-subtypes-doc — Journal, CloudFile, GoogleDocument; Door excluded
(read paths + create operations per BC3 Phase 3a)
* stack-doc-and-smithy — full CRUD + list collectables
* search-filter-additions — additive filter params
* rich-text-project-attachable — Project as Attachable
* recording-bubbleupable-field — additive boolean
* todoset-completed-list-visibility — pending BC3 classification
Tooling:
* spec/api-gaps/schema.json + allowlist-schema.json validate frontmatter
* allowlist.yml records routes that don't warrant a registry entry
(transient nav state, duplicates already covered elsewhere)
* scripts/validate-api-gaps.{sh,rb} — Ruby stdlib only, no gem deps
COORDINATION.md (root) describes the SDK ↔ BC3 plan relationship and the
absorption lifecycle for anyone reading the SDK repo cold.
CONTRIBUTING.md picks up the api-gaps section, the parity lint section,
and points at make generate as the single command to regenerate
everything.
63205bf to
7e9c434
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 34 out of 50 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Both come in transitively via openapi-typescript → @redocly/openapi-core (fast-uri through @redocly/ajv, brace-expansion through minimatch). npm audit on the affected versions reports: fast-uri ≤3.1.1 — high — path traversal + host confusion (GHSA-q3j6-qgpj-74h6 / GHSA-v39h-62p7-jpjc) brace-expansion 4.0.0–5.0.4 — moderate — zero-step sequence hangs the process (GHSA-f886-m6hf-6m8v) Lift both to the patched majors via overrides (alongside the existing minimatch pin). The override path is preferred over plain dependency bumps because the SDK doesn't depend on either package directly — the responsibility for forwarding the fix sits with this repo until the upstream packages cut new releases that pull the patches in transitively. Lands at the bottom of the BC5 stack so the wire-replay PRs above (#294, #301) inherit the fix on rebase.
scripts/check-bucket-flat-parity.sh — drop `--slurpfile spec` and read the spec via positional input instead. The previous form passed the spec to jq twice (once via --slurpfile, once positionally), so jq parsed it twice per invocation. Reading once via positional input then binding `. as \$s` for cross-iteration access preserves the same schema-resolution behavior with a single parse. spec/api-gaps/todoset-completed-list-visibility.md — rewrite the "PR 1 must classify" sentence so the constraint reads on its own, without requiring the umbrella-plan cross-reference. The brief now notes that classification must come from the BC3 side and the brief stays in the registry either way; readers no longer need to know which PR "PR 1" referred to.
Summary
Foundation PR for BC5 release readiness. Additive across the board — no behavior changes, no breaking renames.
Notificationgainsbubble_up_url,bubble_up_atGetMyNotificationsOutputgainsbubble_ups,scheduled_bubble_upsPersongainstagline(alias ofbio)Todogainssteps(reuses existingCardStepshape)Todosetgainstodos_count,completed_loose_todos_count,todos_url,app_todos_urlmemoriesmember documented as observed-current behavior pending BC team's back-compat decisionspec/api-provenance.jsonrestructured..bc3tracks the active branch (five),.compatibility.bc3-masterkeeps the BC4 baseline. Existing tooling reads the same.bc3keys and works unchanged.make generateaggregator runs Smithy build, behavior model, URL routes, provenance sync, and per-language SDKs in dependency order.make check-bucket-flat-parityflags bucket-scoped GET list operations without flat counterparts. Initial allowlist seeded withwebhooks(legitimately per-project).make sync-statusreports drift for the active branch and the BC4 compatibility branch as two clearly-labeled blocks.spec/api-gaps/— 11 entries aligned with the BC3 parity plan's Phase 3 deliverables, plusCOORDINATION.mddescribing the SDK ↔ BC3 plan relationship and the absorption lifecycle.make validate-api-gapsvalidates frontmatter and required body sections (Ruby stdlib only, no gem deps).The api-gap registry is durable: each entry transitions through a documented lifecycle (
no-json-contract→addressed-in-bc3-pr-N→absorbed-in-sdk) with status changes flowing through git history. Living next tobasecamp.smithyinspec/makes the spec-ecosystem mental model explicit — entries describe expected future spec state and link back to Smithy structures on absorption.Commit structure
spec(bc5)— Smithy additions + provenance restructure + parity-lint allowlist seedbuild(make)— generate aggregator + parity lint + branch-aware sync-status + validator make-targetdocs(api-gaps)— API gap registry + COORDINATION.md + validator + CONTRIBUTING updates4-9. One commit per SDK (
ts,ruby,python,kotlin,swift,go) for regenerated artifactsCross-team contract decisions (called out in COORDINATION.md)
Two items the SDK canary will surface that need BC team resolution before release:
memories: []on BC5 — back-compat or accept-and-document.app_todoslists_urltypo — server fix, alias period, or SDK accommodation.Test plan
make smithy-check,make behavior-model-check,make provenance-check,make sync-spec-version-check,make sync-api-version-checkmake go-check-drift,make kt-check-drift,make py-check-drift,make auth-routable-checkmake ts-check,make rb-check,make py-check,make kt-check,make swift-check,make go-checkmake conformance-{go,kotlin,typescript,ruby,python}make check-bucket-flat-parity(1 bucket-scoped list op, allowlisted)make validate-api-gaps(11 entries + allowlist, clean)make sync-statusreports both.bc3and.compatibility.bc3-masterblocksbash scripts/validate-api-gaps.shpasses from a clean shell (env -i ...,ruby --disable-gems ...)make lint-actionsWhat this PR is NOT
This PR is the foundation. It does not include:
check-bc5-compatorchestrator (PR 4)