Upstream sync: repin provenance to bc3 ba105ba7 (2026-07-22), register post-train contracts, codify pin semantics#390
Conversation
Move .bc3 from e52453ff (2026-07-17, one day pre-train) to current master HEAD. Drift across the window is either registry-tracked in spec/api-gaps/ or example-regen catch-up; the modeled-surface fixes and new registry briefs land in the following commits. Propagated via make sync-spec-version + provenance-sync + generate: smithy service version, openapi.json info.version, and all six API_VERSION constants now read 2026-07-22. compatibility.bc3-four stays at 9d73959a — the four branch has zero API drift since (verified 2026-07-22: no doc/api or api controller/view changes).
New briefs (status addressed-in-bc3-pr-12359, merged 2026-07-22): - campfire-line-edit: PUT chats/:c/lines/:id.json, required content, rich-text conversion, creator-only 403/204; SDK PR #295 is the likely absorbing PR. Also records the delete tightening (creator-or-admin). - todoset-direct-todo-create: POST buckets/:b/todosets/:id/todos.json, 201 Todo, project-scoped only; PR-2 CreateTodosetTodo is the vehicle. - schedule-recurrence-writes: full recurrence_schedule param table incl. the week_instance-0 server-hang warning (bc3 #12362 still open), silent-discard-on-invalid, derived response fields, and the already-recurring update redirect; PR-5 vehicle, wire-echo probe gate. search-filter-additions: docs merged — body now lists the documented params (type_names[]/bucket_ids[]/creator_ids[]/since/sort + retained singulars); hold stays, bc3 #12361 is still open.
- OutOfOffice: add optional back_on_date (now documented) and document the disabled state — enabled=false with start/end/back_on dates omitted, not null. start_date/end_date were already optional. - GetMyNotifications: op doc now describes the BC5 grouping (unreads, reads, bubble-ups, scheduled bubble-ups; memories is an always-empty placeholder); Notification.section documents the current enum (inbox/chats/pings/bubbles/mentions — remembered was dropped). - Preferences: time_zone_name returned Rails-style; writes accept IANA identifiers and normalize before saving. - Webhook.recent_deliveries: up to 25 most recent, empty until first delivery. - GetUpcomingSchedule: canonical-path note (BC5 /calendar web view is HTML-only; route shape unchanged). Not changed, verified: EventDetails already models added_person_ids, removed_person_ids, and notified_recipient_ids (the event-example soft flag is already reconciled); Tool/DockItem never modeled the embedded service object, so the CloudFile::Service#code reliability fix has no modeled surface to annotate.
AGENTS.md §Provenance is Mandatory gains the pin-semantics paragraph: the pin asserts drift up to that revision is triaged (absorbed or registered in spec/api-gaps/), not that everything in it is absorbed; a repin is valid when every pin..HEAD drift item is one or the other; the pin never moves backward; compatibility.* pins mark the last verified API-surface state of their branch, not a timestamp. This is the reading the registry and its tooling already implement, and it unblocks reviewer agents that read the AGENTS.md:265 sync rule as requiring HEAD-currency on every sync-shaped PR. COORDINATION.md: contract-authority note now names the current pin (ba105ba7, 2026-07-22) and records the four-branch re-verification — zero API drift since 9d73959a (3 commits, none under doc/api or the API controllers/views).
Follows the spec-side addition; the wrapper unmarshals the raw body, so the tagged field is the whole propagation. Documents the disabled-state omission alongside. Clears check-wrapper-drift.
Spec Change ImpactChanges Detected:
Impact Analysis:
SDK Update Checklist:
|
There was a problem hiding this comment.
Pull request overview
This PR performs an upstream sync to bc3 master at ba105ba7 (2026-07-22), repinning provenance and aligning the Smithy/OpenAPI sources and all SDKs’ declared API version to the new baseline. It also registers post-train contracts in spec/api-gaps/ and codifies the provenance pin semantics in contributor docs to prevent future sync deadlocks.
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:
- Repin provenance (
spec/api-provenance.jsonand downstream copies) to bc3ba105ba7and bump API version to2026-07-22across all SDKs. - Update modeled/docs metadata for notifications grouping, out-of-office (
back_on_date+ disabled-state omission semantics), preferences time zone semantics, webhook deliveries, and reports upcoming schedule description. - Add/update api-gap registry entries for post-train contracts and document pin semantics in
AGENTS.md/ coordination docs.
Reviewed changes
Copilot reviewed 18 out of 27 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| typescript/src/generated/services/reports.ts | Updates generated Reports service docstring for upcoming schedule endpoint. |
| typescript/src/generated/schema.d.ts | Regenerated TypeScript schema types/docs reflecting updated API documentation. |
| typescript/src/generated/openapi-stripped.json | Updates stripped OpenAPI version and descriptions for regenerated TS artifacts. |
| typescript/src/client.ts | Bumps TypeScript SDK API_VERSION constant to 2026-07-22. |
| swift/Sources/Basecamp/Generated/Models/OutOfOffice.swift | Adds generated backOnDate field to OutOfOffice model. |
| swift/Sources/Basecamp/BasecampConfig.swift | Bumps Swift SDK apiVersion constant to 2026-07-22. |
| spec/basecamp.smithy | Bumps Smithy service version and updates docs/shape metadata (OOO, notifications, preferences, webhook, reports). |
| spec/api-provenance.json | Repins bc3 provenance revision/date to ba105ba7 / 2026-07-22. |
| spec/api-gaps/todoset-direct-todo-create.md | Registers a new post-train gap brief for direct todoset todo creation. |
| spec/api-gaps/search-filter-additions.md | Updates the “hold” brief text to reflect the currently documented filter params + defaults. |
| spec/api-gaps/schedule-recurrence-writes.md | Registers a new post-train gap brief for schedule recurrence write parameters (incl. server-hang warning). |
| spec/api-gaps/README.md | Adds the new post-train briefs to the registry index and updates explanatory text. |
| spec/api-gaps/campfire-line-edit.md | Registers a new post-train gap brief for campfire line editing. |
| ruby/lib/basecamp/version.rb | Bumps Ruby SDK API_VERSION constant to 2026-07-22. |
| ruby/lib/basecamp/generated/types.rb | Regenerates Ruby types (adds back_on_date to OutOfOffice and updates generation timestamp). |
| ruby/lib/basecamp/generated/services/reports_service.rb | Updates generated Reports service docstring for upcoming schedule endpoint. |
| python/src/basecamp/generated/types.py | Regenerates Python typed dicts (adds back_on_date to OutOfOffice). |
| python/src/basecamp/_version.py | Bumps Python SDK API_VERSION constant to 2026-07-22. |
| openapi.json | Regenerates top-level OpenAPI (version bump + doc/shape description updates). |
| kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/services/reports.kt | Updates generated Reports service docstring for upcoming schedule endpoint. |
| kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/BasecampConfig.kt | Bumps Kotlin SDK API_VERSION constant to 2026-07-22. |
| go/pkg/generated/client.gen.go | Regenerates Go generated client models/docs (OOO docs + back_on_date, notification section description, webhook deliveries docs). |
| go/pkg/basecamp/version.go | Bumps Go SDK APIVersion constant to 2026-07-22. |
| go/pkg/basecamp/people.go | Updates Go service-layer OutOfOffice struct/docs to include BackOnDate and disabled-state semantics. |
| go/pkg/basecamp/api-provenance.json | Updates Go-packaged provenance pin to ba105ba7 / 2026-07-22. |
| COORDINATION.md | Documents updated provenance baseline and compat pin verification note. |
| AGENTS.md | Codifies provenance pin semantics (triage baseline, non-backward pin, compat pin meaning). |
💡 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: 19361154bb
ℹ️ 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".
TS/Ruby/Kotlin service-doc generators take only the first doc line; the reflowed summary was truncating at 'within a date'. First line is now the complete sentence; the BC5 canonical-path note follows.
Review carefully before merging. Consider a major version bump. |
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Completeness bar: a changed field needs at least one fixture that proves it flows through. Adds spec/fixtures/people/out-of-office.json (values from the pinned doc example) plus enabled- and disabled-state tests at each layer that models the response: Go wrapper unmarshal, TS generated service via MSW, Ruby generated service via webmock. Disabled-state cases pin the omitted-not-null contract.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7ad8125dfb
ℹ️ 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".
There was a problem hiding this comment.
All reported issues were addressed across 13 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Plain String bypassed the sensitive-type pipeline; Person.avatar_url already targets AvatarUrl (@sensitive). behavior-model.json now redacts $.avatar_url for OutOfOfficePerson and the OpenAPI carries format: password, matching Person.
The server ignores content_type on line updates: Chats::LinesController#update
strips it (update_params = line_params.except(:content_type)) and coerces every
edited line to rich text via becomes(Chat::Lines::RichText). Only the line's
creator may edit, and only text/rich-text lines are editable
(Person::Ability#can_edit_chat_line?). Publicly documented in
doc/api/sections/campfires.md ("Update a Campfire line", bc3-api af143f25;
registered as the campfire-line-edit api-gap by basecamp#390).
Drop the dead content_type parameter from UpdateCampfireLineInput and
regenerate all six SDKs; document the rich-text coercion and creator-only
constraint on the operation. Simplify the Go wrapper to
UpdateLine(ctx, campfireID, lineID, content) — no options struct — matching
DeleteLine's shape. The operation is unreleased, so no compatibility concern.
Endpoint semantics were verified against bc3 through 13c84145 via a full
drift audit of e52453ff..13c84145; the provenance pin itself advanced
separately on main (basecamp#390, to ba105ba7), so this commit no longer touches it.
Test adjustments: drop the Go option-validation tests with the options struct,
assert the update body carries only content; drop the Ruby content_type
variant; add 422 mapping coverage for update_line in Ruby and TypeScript.
…ssions Flip spec/api-gaps/campfire-line-edit.md to absorbed-in-sdk with the UpdateCampfireLine Smithy ref, per the absorption plan basecamp#390 registered. While absorbing, refresh DeleteCampfireLine's doc comment with the newly documented creator-or-admin / 403 contract from the same section of doc/api/sections/campfires.md.
…reate-bucket-scope-20260601145434 * origin/main: (28 commits) Upstream sync: repin provenance to bc3 ba105ba7 (2026-07-22), register post-train contracts, codify pin semantics (basecamp#390) ci: pin conformance uv sync to the matrix Python; parse the fan-in gate (basecamp#388) BC5 readiness: pairwise BC4↔BC5 + check-bc5-compat orchestrator + scheduled CI (basecamp#308) CI: fold conformance suites into their language test jobs (basecamp#387) Fix TypeScript SDK Content-Type on GET requests (basecamp#384) BC5 launch reconciliation: registry refresh for the shipped BC5 API train (basecamp#325) BC5 readiness: cross-language wire-replay decoders (basecamp#301) BC5 readiness: Go wrapper forward-compat audit + field-level drift check (basecamp#309) BC5 readiness: TypeScript live wire-capture canary (basecamp#294) BC5 readiness: forward-compat spec, briefs, parity lint (basecamp#293) deps(ts): bump brace-expansion from 5.0.2 to 5.0.7 in /typescript (basecamp#386) typescript: bump fast-uri, brace-expansion, js-yaml overrides for fresh advisories (basecamp#385) deps(actions): bump the actions group with 6 updates (basecamp#382) deps(ruby): bump the bundler-dependencies group in /ruby with 2 updates (basecamp#379) deps(kotlin): bump the gradle-dependencies group (basecamp#383) deps(go): bump github.com/oapi-codegen/oapi-codegen/v2 in /go (basecamp#381) deps(ts): bump the npm-dependencies group in /typescript with 2 updates (basecamp#380) deps(smithy): bump the smithy-gradle-dependencies group (basecamp#378) deps(go): bump github.com/oapi-codegen/runtime (basecamp#377) Todos Update/Edit/Replace: merge-safe writes across all 6 SDKs (basecamp#375) ... # Conflicts: # go/pkg/basecamp/api-provenance.json # go/pkg/basecamp/version.go # go/pkg/generated/client.gen.go # kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/BasecampConfig.kt # openapi.json # python/src/basecamp/_version.py # ruby/lib/basecamp/generated/metadata.json # ruby/lib/basecamp/generated/types.rb # ruby/lib/basecamp/version.rb # spec/api-provenance.json # spec/basecamp.smithy # swift/Sources/Basecamp/BasecampConfig.swift # typescript/src/client.ts # typescript/src/generated/metadata.ts # typescript/src/generated/openapi-stripped.json
…ssions Flip spec/api-gaps/campfire-line-edit.md to absorbed-in-sdk with the UpdateCampfireLine Smithy ref, per the absorption plan basecamp#390 registered. While absorbing, refresh DeleteCampfireLine's doc comment with the newly documented creator-or-admin / 403 contract from the same section of doc/api/sections/campfires.md.
The server ignores content_type on line updates: Chats::LinesController#update
strips it (update_params = line_params.except(:content_type)) and coerces every
edited line to rich text via becomes(Chat::Lines::RichText). Only the line's
creator may edit, and only text/rich-text lines are editable
(Person::Ability#can_edit_chat_line?). Publicly documented in
doc/api/sections/campfires.md ("Update a Campfire line", bc3-api af143f25;
registered as the campfire-line-edit api-gap by basecamp#390).
Drop the dead content_type parameter from UpdateCampfireLineInput and
regenerate all six SDKs; document the rich-text coercion and creator-only
constraint on the operation. Simplify the Go wrapper to
UpdateLine(ctx, campfireID, lineID, content) — no options struct — matching
DeleteLine's shape. The operation is unreleased, so no compatibility concern.
Endpoint semantics were verified against bc3 through 13c84145 via a full
drift audit of e52453ff..13c84145; the provenance pin itself advanced
separately on main (basecamp#390, to ba105ba7), so this commit no longer touches it.
Test adjustments: drop the Go option-validation tests with the options struct,
assert the update body carries only content; drop the Ruby content_type
variant; add 422 mapping coverage for update_line in Ruby and TypeScript.
…ssions Flip spec/api-gaps/campfire-line-edit.md to absorbed-in-sdk with the UpdateCampfireLine Smithy ref, per the absorption plan basecamp#390 registered. While absorbing, refresh DeleteCampfireLine's doc comment with the newly documented creator-or-admin / 403 contract from the same section of doc/api/sections/campfires.md.
The server ignores content_type on line updates: Chats::LinesController#update
strips it (update_params = line_params.except(:content_type)) and coerces every
edited line to rich text via becomes(Chat::Lines::RichText). Only the line's
creator may edit, and only text/rich-text lines are editable
(Person::Ability#can_edit_chat_line?). Publicly documented in
doc/api/sections/campfires.md ("Update a Campfire line", bc3-api af143f25;
registered as the campfire-line-edit api-gap by basecamp#390).
Drop the dead content_type parameter from UpdateCampfireLineInput and
regenerate all six SDKs; document the rich-text coercion and creator-only
constraint on the operation. Simplify the Go wrapper to
UpdateLine(ctx, campfireID, lineID, content) — no options struct — matching
DeleteLine's shape. The operation is unreleased, so no compatibility concern.
Endpoint semantics were verified against bc3 through 13c84145 via a full
drift audit of e52453ff..13c84145; the provenance pin itself advanced
separately on main (basecamp#390, to ba105ba7), so this commit no longer touches it.
Test adjustments: drop the Go option-validation tests with the options struct,
assert the update body carries only content; drop the Ruby content_type
variant; add 422 mapping coverage for update_line in Ruby and TypeScript.
…ssions Flip spec/api-gaps/campfire-line-edit.md to absorbed-in-sdk with the UpdateCampfireLine Smithy ref, per the absorption plan basecamp#390 registered. While absorbing, refresh DeleteCampfireLine's doc comment with the newly documented creator-or-admin / 403 contract from the same section of doc/api/sections/campfires.md.
* feat(campfires): add UpdateCampfireLine operation
Adds an UpdateCampfireLine operation across all six SDKs, generated from
the Smithy spec. Maps PUT /chats/{campfireId}/lines/{lineId}, which the
Basecamp API accepts but the spec did not previously expose.
- Smithy: new operation with Campfire tag, registered in service operations
- Generated clients regenerated for Go, TypeScript, Ruby, Python, Swift, Kotlin
- Service generator mappings (TS, Ruby, Python, Swift, Kotlin) updated to
rename UpdateCampfireLine -> updateLine / update_line
- Go service wrapper UpdateLine returns the re-fetched line (API responds 204)
- Go, Ruby, TypeScript tests cover happy path and validation
- AGENTS.md operation count refreshed (175 -> 204)
Verified: PUT /chats/{c}/lines/{l} with {content,content_type} returns 204
against a real Basecamp account; the line content updates as expected.
* fix(campfires): align UpdateCampfireLine with server semantics
The server ignores content_type on line updates: Chats::LinesController#update
strips it (update_params = line_params.except(:content_type)) and coerces every
edited line to rich text via becomes(Chat::Lines::RichText). Only the line's
creator may edit, and only text/rich-text lines are editable
(Person::Ability#can_edit_chat_line?). Publicly documented in
doc/api/sections/campfires.md ("Update a Campfire line", bc3-api af143f25;
registered as the campfire-line-edit api-gap by #390).
Drop the dead content_type parameter from UpdateCampfireLineInput and
regenerate all six SDKs; document the rich-text coercion and creator-only
constraint on the operation. Simplify the Go wrapper to
UpdateLine(ctx, campfireID, lineID, content) — no options struct — matching
DeleteLine's shape. The operation is unreleased, so no compatibility concern.
Endpoint semantics were verified against bc3 through 13c84145 via a full
drift audit of e52453ff..13c84145; the provenance pin itself advanced
separately on main (#390, to ba105ba7), so this commit no longer touches it.
Test adjustments: drop the Go option-validation tests with the options struct,
assert the update body carries only content; drop the Ruby content_type
variant; add 422 mapping coverage for update_line in Ruby and TypeScript.
* test(py): cover campfire line operations
Backfill service tests for create_line/get_line/update_line/delete_line.
update_line gets happy-path (204 -> None, body carries only content) and
422 ValidationError cases in both the sync and async clients.
* test(kt): cover campfire line operations
Backfill CampfiresServiceTest: createLine/getLine/deleteLine happy paths,
updateLine PUT with a content-only body, and 422 -> Validation mapping.
* test(swift): cover campfire line operations
Backfill GeneratedServiceTests: createLine/getLine/deleteLine happy paths,
updateLine PUT with a content-only body, and 422 -> .validation mapping.
* docs: refresh SPEC.md operation counts (181 -> 204)
behavior-model.json now carries 204 operations (66 idempotent, 138 not);
the retry-pattern claims (three (max, base_delay_ms) shapes, all
retry_on [429, 503]) were re-verified against the model and still hold.
* spec(campfires): absorb campfire-line-edit gap; document delete permissions
Flip spec/api-gaps/campfire-line-edit.md to absorbed-in-sdk with the
UpdateCampfireLine Smithy ref, per the absorption plan #390 registered.
While absorbing, refresh DeleteCampfireLine's doc comment with the
newly documented creator-or-admin / 403 contract from the same section
of doc/api/sections/campfires.md.
---------
Co-authored-by: Jeremy Daer <jeremy@hey.com>
Upstream sync + provenance repin (2026-07-22)
Repins
spec/api-provenance.jsonfrome52453ff(2026-07-17, one day before bc3's BC5 API train merged) to current bc3masterHEADba105ba7(2026-07-22), closes the registry gaps the window opened, fixes modeled-surface doc/optionality drift, and codifies the pin semantics that make the repin valid.Why now
AGENTS.md:265 says every sync MUST update the provenance pin to the upstream bc3 HEAD — and reviewer agents apply that rule to every sync-shaped PR, deadlocking on the stale pin. The pin was deliberately held back by #293 while the BC5-readiness stack was in flight; with the stack merged and #325's registry refresh completing the triage, the repin is legitimate under the pin's actual meaning: drift up to the pin is triaged (absorbed into the spec or registered in
spec/api-gaps/), not "everything at the pin is absorbed". That reading is now written down in AGENTS.md §Provenance is Mandatory, so the deadlock class can't recur.Coverage audit — every changed doc section
e52453ff..ba105ba7(55 files)campfires.mdcampfire-line-edit(bc3 #12359):PUT /chats/:c/lines/:id.json, requiredcontent, rich-text conversion, creator-only, 204/403. Delete tightening (creator-or-admin, 403) recorded in the same brief. SDK PR #295 already modelsUpdateCampfireLineand is the likely absorbing PR.todos.mdtodoset-direct-todo-create(bc3 #12359):POST /buckets/:b/todosets/:id/todos.json→ 201 Todo, project-scoped only. §Q PR-2CreateTodosetTodois the vehicle.schedule_entries.mdschedule-recurrence-writes(bc3 #12359, cURL alignment #12363): fullrecurrence_schedulewrite contract incl. theweek_instance: 0server-hang warning (bc3 #12362 still open). §Q PR-5 vehicle; wire-echo probe remains the pre-modeling gate.search.mdsearch-filter-additions: documented params now listed (type_names[]/bucket_ids[]/creator_ids[]/since/sort+ deprecated-retained singulars). Hold stays — bc3 #12361 ("Search API: query-faithful params and root cache") is still open.calendars.md,my_notes.md,everything.md,cloud_files.md,google_documents.mdcalendar,scratchpad,everything-aggregates,recordable-subtypes-doc. Absorption stays in the §Q queue.out_of_office.mdenabled: falsewithstart_date/end_date/back_on_dateomitted (not null);back_on_dateadded as optional output member (spec + Go wrapper propagation).my_notifications.mdNotification.sectiondocuments the current enum (inbox/chats/pings/bubbles/mentions—remembereddropped; the SDK never enum-modeled it, doc-only fix).people.mdtime_zone_namereturned Rails-style, IANA accepted on write and normalized. Profile-update docs unchanged upstream —UpdateMyProfileInputuntouched. Person example fields (taglineetc.) are example-regen catch-up (see below).webhooks.mdrecent_deliveriesdocumented as up-to-25, empty until first delivery.reports.mdGetUpcomingScheduledoc notes/reports/schedules/upcoming.jsonis preserved as the canonical API path (BC5/calendarweb view is HTML-only; route shape unchanged — the new server-side controller restored BC4 ordering, no SDK impact).events.mdnotified_recipient_idssoft flag is already reconciled —EventDetailsmodelsadded_person_ids,removed_person_ids, andnotified_recipient_ids.tools.mdCloudFile::Service#as_jsonnow reliably populatescodein the dock-toolserviceobject) has no modeled surface — neitherToolnorDockItemmodels the embeddedserviceobject. Absorbingserviceis future work with the §Q queue if demand appears.README.md,account.md,attachments.md,boosts.md,card_table_cards.md,card_table_columns.md,card_table_steps.md,card_tables.md,chatbots.md,client_approvals.md,client_correspondences.md,client_replies.md,comments.md,documents.md,forwards.md,gauges.md,hill_charts.md,inbox_replies.md,inboxes.md,lineup_markers.md,message_boards.md,message_types.md,messages.md,my_assignments.md,projects.md,question_answers.md,question_reminders.md,questionnaires.md,questions.md,schedules.md,subscriptions.md,templates.md,timeline.md,timesheets.md,todolist_groups.md,todolists.md,todosets.md,uploads.md,vaults.mdtagline/company/avatar_url, rich-text*_attachments, my_assignments nested extras, project dock/membership objects, …), regenerated from live BC5 by the #11629 tooling. No contract changes. Pre-existing SDK gaps here stay tracked where they are (rich-text attachments + counts: #353/#355).Zero wire-shape changes to modeled partials in the window: the six modified pre-existing jbuilders are cache-key/helper/comment refactors.
BC4 compat pin
compatibility.bc3-fourstays at9d73959a(2026-06-12). Re-verified 2026-07-22: thefourbranch has zero API drift since — 3 commits, none touchingdoc/api/,app/views/api/, or the API controllers. The compat pin marks the last verified API-surface state, not a timestamp (now codified in AGENTS.md).Policy
AGENTS.md §Provenance is Mandatory gains the pin-semantics paragraph: pin = triage baseline; past-pin contracts live in
spec/api-gaps/withaddressed-in-bc3-pr-Nuntil absorbed; a repin is valid when everypin..HEADdrift item is absorbed or registered; the pin never moves backward;compatibility.*pins are verified states, not timestamps.Unblocks
056a356e→ae96a694). Recipe (will comment on the PR after merge): rebase onto main, drop itsspec/api-provenance.jsonhunk (its synced behavior was validated atae96a694, which the current pin covers), fix its 2 unresolved Copilot nits.campfire-line-edit.mdnames it the likely absorbing PR forUpdateCampfireLine.Verification
make checkgreen (incl.sync-spec-version-check,provenance-check,validate-api-gapsat 15 entries, per-language conformance).make sync-status: primary and compat drift blocks both empty.API_VERSIONconstants (Go/Kotlin/Python/Ruby/Swift/TS) read2026-07-22;grep -rn e52453ffhits nothing.doc/api/sections/*.mdatba105ba7.Summary by cubic
Sync to Basecamp 3 master (2026-07-22), bump the API version to 2026-07-22 across SDKs, and refine OutOfOffice modeling: add
back_on_date, clarify disabled-state omission, and typeOutOfOfficePerson.avatar_urlas sensitiveAvatarUrl. Registers post-train contracts and codifies provenance pin semantics.New Features
back_on_dateand defines disabled state as omitting dates;OutOfOfficePerson.avatar_urlis now modeled and marked sensitive (AvatarUrl, OpenAPIformat: password); Notifications inbox docs reflect BC5 grouping andsectionenum; Preferencestime_zone_namereturns Rails-style and accepts IANA on write; Webhookrecent_deliveriescapped at 25; Reports upcoming summary and canonical-path note.spec/api-gaps/briefs —campfire-line-edit,todoset-direct-todo-create,schedule-recurrence-writes.search-filter-additionsupdated but still on hold pending upstream param rework.Refactors
openapi.json, and all SDKAPI_VERSIONconstants. Pin semantics documented inAGENTS.md;compatibility.bc3-fourremains at the last verified state.back_on_date, disabled-state shape (ongoing=false, no dates), enabled-state ongoing=true, andOutOfOfficePerson.avatar_url; added fixturespec/fixtures/people/out-of-office.json. Behavior model now redactsOutOfOfficePerson.avatar_url.Written for commit bd40ab9. Summary will update on new commits.