Skip to content

Absorb everything-aggregates flat family (bc3 #11627, PR-5 of 2)#435

Open
jeremy wants to merge 6 commits into
doors-external-linksfrom
everything-flat-family
Open

Absorb everything-aggregates flat family (bc3 #11627, PR-5 of 2)#435
jeremy wants to merge 6 commits into
doors-external-linksfrom
everything-flat-family

Conversation

@jeremy

@jeremy jeremy commented Jul 25, 2026

Copy link
Copy Markdown
Member

Closes #434 (partially — flat family only). Part of the post-#401 BC3 follow-up absorption program (PR-5, the LARGE one, two-phase).

Stacked on #431 (PR-4) → #426#424#419#416. Base is doors-external-links; review the PR-5 commit only. Will retarget to main as the stack merges.

Summary

BC5's account-wide recording listings (documented by bc3 #11627) had no SDK surface. This adds a new EverythingService with the flat family (8 ops), mirroring the flat-aggregate pattern of GetMyAssignments. The bucket-grouped family (9 sub-routes) lands in PR-5b; the registry entry stays partial-coverage until then.

Absorbed

  • 6 Link-paginated rootsGetEverythingMessages/Comments/Checkins/Forwards (element = the generic Recording projection the wire returns, embedding bucket), GetEverythingBoosts (Boost), GetEverythingFiles.
  • 2 unpaginated oldest-first arraysGetEverythingOverdueTodos (Todo), GetEverythingOverdueCards (Card) — bare arrays via smithy-bare-arrays, tested with no Link-following.
  • /files.json heterogeneous (Upload + Document + attachment-envelope) → optional-field superset EverythingFile with kind + repeatable people_ids[] filters.

Runtime decode proof (all six SDKs)

A non-empty test decoding all three file variants in one array — Go, TS, Ruby, Python, Kotlin, Swift. Kotlin needed EverythingFile added to the generator TYPE_ALIASES (else it fell back to ListResult<JsonElement>); it now returns ListResult<EverythingFile>. Go tests also cover multi-page Link-following, unpaginated-with-Link-header-ignored, and the kind/people_ids[] filters.

Wiring

Service auto-derives from the Everything tag; client wiring added where hand-written (Go accessor, TS defineService, Ruby method, Python sync+async properties; Kotlin/Swift auto-wired).

Verification

make generate && make check — clean (all six SDK suites, conformance, wrapper/Kotlin drift, 24 api-gap entries). everything-aggregates.mdpartial-coverage. Conformance paths.json/dispatch + per-group canary entries tracked as follow-ups landing with PR-5b.


Summary by cubic

Adds a new EverythingService that exposes account‑wide “everything” listings (flat family, 8 ops) across all SDKs. Partially addresses #434 and aligns with bc3 #11627; bucket‑grouped routes will ship in PR‑5b.

  • New Features

    • New EverythingService with 8 ops: GetEverythingMessages, GetEverythingComments, GetEverythingCheckins, GetEverythingForwards, GetEverythingBoosts, GetEverythingFiles, GetEverythingOverdueTodos, GetEverythingOverdueCards.
    • Pagination: Link-following for the six recency-ordered roots; overdue todos/cards return full arrays.
    • /files.json heterogeneous feed modeled as EverythingFile with kind and repeatable people_ids[] filters; Go uses nullable FlexInt for width/height.
    • Wired across Go/TypeScript/Ruby/Python/Kotlin/Swift; OpenAPI/smithy/metadata updated; tests prove decode and pagination.
  • Migration

    • No breaking changes. New accessors: Go accountClient.Everything(), TypeScript client.everything, Python client.everything, Ruby client.everything, Kotlin accountClient.everything, Swift accountClient.everything.

Written for commit 62dad6f. Summary will update on new commits.

Review in cubic

jeremy added 6 commits July 24, 2026 21:10
…e api-gaps entries

Advance the bc3 provenance pin from ca1d34bc to d7bc88da (bc3 master at
2026-07-24). The ca1d34bc..d7bc88da range is 30 commits, all reviewed
no-ops for the SDK: 26 UI/CSS/JS/lexxy commits plus the duplicate-cookie
migration auth commits (88cb86d2a/52f1e9974/7d86f1d06), which touch only
the by_cookie session-cookie concern and its test — no route, controller,
doc, or modeled API-contract change. Pin date is unchanged (2026-07-24),
so no SDK version bump.

Also correct two api-gaps entries whose upstream tails have since closed:

- dock-tool-create-contract: bc3#12366 (8f938281) rewrote
  doc/api/sections/tools.md for the tool_type contract, closing the doc
  tail the entry still tracked as the open bc3#12364 note. Add top-level
  bc3_pr: 12366.
- schedule-recurrence-writes: bc3#12362 (ec17b83c) merged and now rejects
  week_instance: 0 (and other uncomputable schedules) at create time, so
  the mandatory SDK-side guard is downgraded to optional hygiene.
The dock-tool create endpoint gained an optional top-level
visible_to_clients boolean in bc3 #12386 (bee714c74). Only tool types that
manage their own client visibility — Chat::Transcript and Kanban::Board,
which otherwise start hidden — honor it; every other tool type ignores it
and inherits the project default.

Absorb it as a tri-state optional, mirroring the six content-create inputs
from #401:

- Smithy: add visible_to_clients: Boolean to CreateToolInput (plain Boolean
  → Go *bool), documenting the two-tool-type honoring rule on the member.
- Go: CreateToolOptions.VisibleToClients *bool with a pass-through in
  ToolsService.Create; nil omits the field, explicit false reaches the wire.
- Tests: Go tri-state transport test plus one body-encoding test in each of
  TS/Ruby/Python/Kotlin/Swift asserting explicit false is sent, not dropped.

Flip dock-tool-visible-to-clients.md to absorbed-in-sdk with the smithy_ref
and update the api-gaps README row.
The merged doc/api/sections/timeline.md and the bc3 timeline event view
(api/timelines/events/_event.json.jbuilder) carry event fields the SDK did
not yet type. No new operations — GetProgressReport, GetProjectTimeline, and
GetPersonProgress already model the three routes. Extend TimelineEvent:

- kind: kept an open, non-exhaustive String (documentation only, no closed
  enum) — BC3 adds new kinds over time; document common values including the
  live-only project_access_changed, dock_created, google_document_created.
- data: new TimelineEventData sub-struct for schedule_entry_* events. Per the
  bc3 view (starts_at_date_or_time), starts_at/ends_at are date-or-timestamp
  (a bare date when all_day is true), so they are NOT plain timestamps:
  modeled as ISO8601Timestamp mirroring ScheduleEntry, with a Go enhancement
  pass mapping them to types.FlexibleTime; other SDKs type them as strings.
- avatars_sample: StringList (chat-rollup participants).
- attachments: heterogeneous per the bc3 view — an upload-kind recording
  contributes its full Upload shape, every other recording a rich-text
  attachment/blob partial. These variants share no required field set, so
  reusing an existing attachment shape is not possible. Modeled as an
  optional-field superset struct (TimelineAttachment) so one element type
  decodes either variant (the untagged-polymorphism default; no union needed).
  width/height get the nullable *types.FlexInt Go enhancement (float-spelled
  1024.0, null for non-image blobs), matching RichTextAttachment.

Runtime decode proof: every SDK (Go, TS, Ruby, Python, Kotlin, Swift) has a
non-empty, per-variant test decoding BOTH attachment variants in one array,
plus the all-day date-only data payload and a non-empty avatars_sample. The
Go wrapper's TimelineAttachment routes decoding through the generated FlexInt
type via a custom UnmarshalJSON (mirroring RichTextAttachment).

Add a GetProgressReport entry to the live-my-surface canary (validates
statically; live canary dormant) and flip activity-timeline.md to
absorbed-in-sdk with smithy_refs.
doc/api/sections/my_notifications.md (codified by bc3 #11628) documents the
BC5 bubble-up surface that memories-emptied-regression.md explicitly defers
to a separate additive PR. Absorb it:

- GetMyNotificationsOutput: add required bubble_ups_count and
  scheduled_bubble_ups_count (top-level UI counts, present independent of the
  limit_bubble_ups cap and even when the scheduled_bubble_ups array is
  omitted).
- GetMyNotificationsInput: add optional limit_bubble_ups boolean @httpquery
  (true caps bubble_ups at 2 current items and omits scheduled_bubble_ups).
- New GetBubbleUps operation (GET /my/readings/bubble_ups.json): a paginated
  bare array (50/page, Link-header pagination, page query param) of current
  bubble-ups first (most recently bubbled up) then scheduled bubble-ups
  (scheduled time). Same Notification item shape as GetMyNotifications. Added
  to the service operations list and tagged MyNotifications.

Go wrapper: MyNotificationsService.BubbleUps follows the Link header across
all pages by default; a positive page returns only that page. Get gained a
non-breaking WithLimitBubbleUps() functional option. Tests: a multi-page
Link-following pagination test (with X-Total-Count metadata and
current-then-scheduled ordering), a single-page test, and a test proving
limit_bubble_ups=true sends the param and decodes a response omitting
scheduled_bubble_ups while keeping the counts.

The grouped bubble_ups/scheduled_bubble_ups arrays and their item fields were
already modeled and are not re-added. memories-emptied-regression.md is left
intact; a new bubble-ups-surface.md entry records this absorption. Updated the
GetMyNotifications conformance validator fixtures for the now-required counts
and added a GetBubbleUps canary entry (validates statically; live dormant).
…mposite (bc3 #12375)

bc3 #12375 documents the external-link (historically "door") resource. A
pre-implementation spike scoped this to the cleanly-absorbable surface:

Absorbed:
- Make Door reachable through the EXISTING polymorphic ListRecordings query
  (GET /projects/recordings.json?type=Door) rather than a new operation:
  ListRecordings already carries a type query and Recording.url. Add Door to
  the RecordingType documented enum and optional position/description/service
  (DoorService struct) to the shared Recording projection.
- Go wrapper: RecordingTypeDoor constant, clean DoorService type, door fields
  on Recording, mapper wiring. Runtime decode tests prove the full door shape
  (external url + service struct + description + position) decodes through the
  projection, and that a non-door recording leaves the door fields empty.
- Get/rename/trash already reuse GetTool/UpdateTool/DeleteTool (no work).
- type=Door ListRecordings canary entry (validates statically; live dormant).

Deferred as residual gaps (entry is partial-coverage, not absorbed-in-sdk):
- Create (POST .../dock/doors.json) returns 302 + empty body redirecting
  cross-origin. The spike found the six SDK transports handle this
  inconsistently — Go/TS/Kotlin/Swift follow the redirect; Python/Ruby do not
  but face empty-body decode — so modeling "return only the 302/empty"
  response needs a cross-cutting per-operation transport change, out of scope
  for an additive absorption.
- image thumbnail is multipart-only; unmodeled.
- The SPEC §18 create-and-discover composite depends on a shippable create.

Additive only (Door enum + optional Recording fields); no operation change.
BC5's account-wide recording listings (everything/*_controller.rb, documented
by bc3 #11627 in doc/api/sections/everything.md) had no SDK surface. Add a new
EverythingService with the 8 flat-family operations, mirroring the flat
aggregate pattern of GetMyAssignments:

- Six recency-ordered, Link-paginated roots: GetEverythingMessages/Comments/
  Checkins/Forwards (element = the generic Recording projection the wire
  actually returns, embedding bucket), GetEverythingBoosts (element = Boost,
  with its booster + nested recording), and GetEverythingFiles.
- Two unpaginated, oldest-due-date-first arrays: GetEverythingOverdueTodos
  (Todo) and GetEverythingOverdueCards (Card), modeled as plain full arrays
  (single-member output, no pagination → bare array via smithy-bare-arrays)
  and tested with no Link-following.
- /files.json is heterogeneous (Upload + Document + attachment-envelope):
  modeled as the optional-field superset EverythingFile with the kind and
  repeatable people_ids[] filters. Width/height get the nullable *FlexInt Go
  enhancement (and Kotlin needed EverythingFile added to the generator
  TYPE_ALIASES so it emits a typed model instead of JsonElement).

Runtime decode proof for the heterogeneous feed in every SDK (Go, TS, Ruby,
Python, Kotlin, Swift): a non-empty test decoding all three file variants in
one array. Go wrappers add multi-page Link-following (paginated roots) and
plain full-array decode (overdue); Go tests cover multi-page pagination,
unpaginated-with-Link-header-ignored, per-variant files decode, and the
kind/people_ids[] filters.

Service auto-derives from the Everything tag; client wiring added where
hand-written (Go accessor, TS defineService, Ruby method, Python sync+async
properties; Kotlin/Swift auto-wired).

everything-aggregates.md moves to partial-coverage with a two-phase absorption
note; it flips to absorbed-in-sdk only after PR-5b models the bucket-grouped
family. Conformance paths.json + per-runner dispatch and per-group canary
entries are tracked as follow-ups landing with PR-5b.
Copilot AI review requested due to automatic review settings July 25, 2026 06:02
@github-actions github-actions Bot added typescript Pull requests that update TypeScript code ruby Pull requests that update the Ruby SDK go kotlin swift spec Changes to the Smithy spec or OpenAPI labels Jul 25, 2026
@github-actions

Copy link
Copy Markdown

Spec Change Impact

  • Modifications:

    • Operations/types/resources have been modified (details not provided in the diff snippet).
  • Additions: No new operations/types/resources were explicitly mentioned.

  • Removals: No removed operations/types/resources were explicitly mentioned, but if any exist, this is a breaking API change.

  • SDK Regeneration: Required for all SDKs due to spec changes, even for non-breaking changes.

  • Breaking Change: Unable to confirm without more details. If operations or fields were removed, this is a breaking change.

Checklist of SDKs Needing Updates:

  • Go
  • TypeScript
  • Ruby
  • Kotlin
  • Swift

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Not ready to approve

The Go wrapper’s page parameter is currently not applied to requests (so page>1 can’t work as documented), and the TS/Python client typings have a few inconsistencies that should be corrected before merging.

Pull request overview

Adds first-phase SDK surface for BC5 “everything” account-wide aggregates (flat family, 8 ops) by introducing a new EverythingService across all six SDKs, backed by Smithy/OpenAPI updates, runtime decode fixtures for the heterogeneous /files.json feed, and updated api-gaps registry status.

[!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:

  • Model and generate the flat “everything” aggregate routes (messages/comments/checkins/forwards/boosts/files + overdue todos/cards) and tag them into a new Everything service group.
  • Add per-SDK wiring so client.everything / account.everything is available, plus metadata/path mapping updates.
  • Add runtime decode tests proving /files.json heterogeneous variants (Upload/Document/Attachment) decode correctly across SDKs.
File summaries
File Description
typescript/tests/services/everything.test.ts Adds TS decode test for heterogeneous /files.json results.
typescript/src/generated/services/index.ts Exports generated EverythingService.
typescript/src/generated/services/everything.ts Implements generated TS EverythingService methods for the flat family.
typescript/src/generated/schema.d.ts Adds new operations/paths and EverythingFile schema typing.
typescript/src/generated/path-mapping.ts Maps Everything endpoints to operation IDs for routing/metadata.
typescript/src/generated/openapi-stripped.json Updates stripped OpenAPI with Everything routes/schemas used by TS generator.
typescript/src/generated/metadata.ts Adds retry/pagination metadata entries for Everything operations.
typescript/src/client.ts Wires client.everything service accessor.
swift/Tests/BasecampTests/GeneratedServiceTests.swift Adds Swift runtime decode test for heterogeneous /files.json.
swift/Sources/Basecamp/Generated/Services/EverythingService.swift Adds generated Swift EverythingService.
swift/Sources/Basecamp/Generated/Models/EverythingFile.swift Adds generated Swift EverythingFile model.
swift/Sources/Basecamp/Generated/Metadata.swift Registers retry metadata for Everything operations.
swift/Sources/Basecamp/Generated/AccountClient+Services.swift Wires Swift account.everything accessor.
spec/overlays/tags.smithy Tags the 8 flat-family operations into the Everything service group.
spec/basecamp.smithy Adds Smithy operations + EverythingFile superset shape.
spec/api-gaps/README.md Marks everything-aggregates as partial-coverage pending PR-5b.
spec/api-gaps/everything-aggregates.md Updates registry entry with phased plan/status + smithy refs.
scripts/enhance-openapi-go-types.sh Enhances EverythingFile width/height to nullable FlexInt in Go OpenAPI post-pass.
ruby/test/basecamp/services/everything_service_test.rb Adds Ruby decode test for heterogeneous /files.json.
ruby/lib/basecamp/generated/types.rb Adds generated Ruby EverythingFile type class.
ruby/lib/basecamp/generated/services/everything_service.rb Adds generated Ruby EverythingService.
ruby/lib/basecamp/generated/metadata.json Registers Ruby operation metadata for Everything operations.
ruby/lib/basecamp/client.rb Wires Ruby client.everything accessor.
python/tests/services/test_everything.py Adds Python decode test for heterogeneous /files.json.
python/src/basecamp/generated/types.py Adds EverythingFile TypedDict.
python/src/basecamp/generated/services/everything.py Adds generated Python sync/async EverythingService.
python/src/basecamp/generated/services/init.py Exposes Everything services via package exports.
python/src/basecamp/generated/metadata.json Registers retry metadata for Everything operations.
python/src/basecamp/client.py Wires Python sync client.everything property.
python/src/basecamp/async_client.py Wires Python async client.everything property.
openapi.json Adds Everything paths/operations/schemas to the canonical OpenAPI output.
kotlin/sdk/src/commonTest/kotlin/com/basecamp/sdk/EverythingFilesDecodeTest.kt Adds Kotlin decode test for heterogeneous /files.json.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/services/Types.kt Adds options type for Everything files filters/pagination.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/services/everything.kt Adds generated Kotlin EverythingService.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/ServiceAccessors.kt Wires Kotlin accountClient.everything accessor.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/models/EverythingFile.kt Adds generated Kotlin EverythingFile model.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/sdk/generated/Metadata.kt Registers retry config entries for Everything operations.
kotlin/generator/src/main/kotlin/com/basecamp/sdk/generator/Config.kt Adds EverythingFile to Kotlin generator TYPE_ALIASES.
go/pkg/basecamp/url-routes.json Registers Everything routes in Go URL routing table.
go/pkg/basecamp/everything.go Adds Go EverythingService wrapper + EverythingFile public model conversion.
go/pkg/basecamp/everything_test.go Adds Go tests for Link-following, filters, and heterogeneous decode.
go/pkg/basecamp/client.go Wires Go AccountClient.Everything() accessor.
behavior-model.json Adds behavior-model entries for Everything operations (retry/pagination/readonly).

Review details

  • Files reviewed: 21/44 changed files
  • Comments generated: 1
  • Review effort level: Low

Note

Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +176 to +180
resp, err := s.client.parent.gen.GetEverythingMessagesWithResponse(ctx, s.client.accountID)
if err != nil {
return nil, err
}
return s.finishRecordingsPage(ctx, resp.HTTPResponse, resp.Body, resp.JSON200, page)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 62dad6fa41

ℹ️ 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".

Comment on lines +23 to +24
describe("everythingFiles", () => {
it("should decode the heterogeneous /files.json feed: Upload, Document, and Attachment variants in one array", async () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add contract tests for all eight operations

The new TypeScript suite exercises only the happy path for everythingFiles, and the Ruby and Python suites have the same limitation; the other seven operations have neither happy-path nor error tests, while everythingFiles has no error test. Consequently, incorrect routes, response shapes, and error propagation for most of this service can ship undetected. The repository's completeness bar explicitly requires happy-path and error coverage in all three SDKs for every new operation.

AGENTS.md reference: AGENTS.md:L305-L307

Useful? React with 👍 / 👎.

@@ -1,5 +1,6 @@
export { AccountService } from "./account.js";
export { AttachmentsService } from "./attachments.js";
export { EverythingService } from "./everything.js";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Export EverythingService from the package root

Although this adds EverythingService to the generated services barrel, the package entry point typescript/src/index.ts explicitly enumerates public service exports and is not updated here. Consumers therefore cannot import EverythingService or its option types from @37signals/basecamp, unlike the other public services; add the corresponding root export.

AGENTS.md reference: AGENTS.md:L304-L304

Useful? React with 👍 / 👎.

Comment thread spec/basecamp.smithy
Comment on lines +8534 to +8535
// Rails controller namespace, not part of the URL). Documented by BC3 #11627 in
// doc/api/sections/everything.md. This is the flat family: six recency-ordered,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Refresh provenance for this upstream absorption

This Smithy addition explicitly absorbs the BC3 #11627 contract, but the commit does not update spec/api-provenance.json. That leaves no recorded upstream HEAD/date for the sync and prevents the provenance pin from demonstrating which BC3 state was verified; refresh the pin and run make provenance-sync.

AGENTS.md reference: AGENTS.md:L265-L270

Useful? React with 👍 / 👎.

return nil, err
}
defer done(&err)
resp, err := s.client.parent.gen.GetEverythingMessagesWithResponse(ctx, s.client.accountID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Forward the requested page in Go

When a caller passes page > 1, this request still invokes the generated operation without a page parameter, so it always fetches the API's default first page and merely disables Link following afterward. The same omission affects Comments, Checkins, Forwards, Boosts, and Files. Add the page query parameter to the six Smithy inputs, regenerate, and pass it through so requesting page 2 does not silently return page 1.

AGENTS.md reference: AGENTS.md:L76-L76

Useful? React with 👍 / 👎.

* const result = await client.everything.everythingBoosts();
* ```
*/
async everythingBoosts(options?: EverythingBoostsEverythingOptions): Promise<components["schemas"]["GetEverythingBoostsResponseContent"]> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve ListResult in the TypeScript return types

For everythingBoosts, the declared response alias resolves to Boost[], even though requestPaginated returns ListResult<Boost> and the method documentation promises .meta.totalCount. TypeScript consumers therefore get a compile-time error when accessing the advertised metadata; everythingFiles has the same issue. Update the generator's entity mapping so these signatures are ListResult<Boost> and ListResult<EverythingFile>.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 44 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="go/pkg/basecamp/everything.go">

<violation number="1" location="go/pkg/basecamp/everything.go:62">
P3: False API values are lost when callers marshal `EverythingFile`. Keep JSON tags on these response booleans without `omitempty` so `false` is represented.</violation>

<violation number="2" location="go/pkg/basecamp/everything.go:63">
P3: Attachment variants with no timestamps serialize zero-time sentinels instead of preserving field absence. Use `*time.Time` for optional timestamps and populate them only when the generated value is present/non-zero.</violation>

<violation number="3" location="go/pkg/basecamp/everything.go:169">
P2: Passing a positive page returns the server's first page, not the requested page, across every paginated Everything method. Add `page` to the initial request query (for example via a request editor) or document/remove this parameter rather than promising a page-specific result.</violation>
</file>

<file name="typescript/src/client.ts">

<violation number="1" location="typescript/src/client.ts:411">
P2: EverythingService is wired into the client (import, type declaration, `defineService`) but not re-exported from `index.ts`, so it is missing from the package's public API surface. All other services in the codebase are re-exported — please add a re-export block for `EverythingService` (and any newly exported types like `EverythingFile`) to `index.ts` following the same pattern.</violation>
</file>

<file name="python/src/basecamp/client.py">

<violation number="1" location="python/src/basecamp/client.py:351">
P1: The new `account.everything` accessor exposes overdue methods with the wrong response contract: `get_everything_overdue_cards` and `get_everything_overdue_todos` call `_request` and are typed as `dict[str, Any]`, but these routes return bare arrays. A valid overdue response therefore violates the SDK method contract and can break callers expecting the documented list result; the generated service should use the bare-array response handling and list return type for both sync and async methods.</violation>
</file>

<file name="typescript/src/generated/services/everything.ts">

<violation number="1" location="typescript/src/generated/services/everything.ts:182">
P2: `everythingFiles` is paginated at runtime, but the declared return type is a plain array response alias. Using `ListResult<...>` in the signature preserves typed access to pagination metadata and matches the method’s actual return contract.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

def everything(self):
from basecamp.generated.services.everything import EverythingService

return self._service("everything", lambda: EverythingService(self))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The new account.everything accessor exposes overdue methods with the wrong response contract: get_everything_overdue_cards and get_everything_overdue_todos call _request and are typed as dict[str, Any], but these routes return bare arrays. A valid overdue response therefore violates the SDK method contract and can break callers expecting the documented list result; the generated service should use the bare-array response handling and list return type for both sync and async methods.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At python/src/basecamp/client.py, line 351:

<comment>The new `account.everything` accessor exposes overdue methods with the wrong response contract: `get_everything_overdue_cards` and `get_everything_overdue_todos` call `_request` and are typed as `dict[str, Any]`, but these routes return bare arrays. A valid overdue response therefore violates the SDK method contract and can break callers expecting the documented list result; the generated service should use the bare-array response handling and list return type for both sync and async methods.</comment>

<file context>
@@ -344,6 +344,12 @@ def timeline(self):
+    def everything(self):
+        from basecamp.generated.services.everything import EverythingService
+
+        return self._service("everything", lambda: EverythingService(self))
+
     @property
</file context>

// Messages returns every message across all accessible projects, newest-first.
// Pass a positive page to return only that page; page 0 follows the Link header
// across all pages.
func (s *EverythingService) Messages(ctx context.Context, page int32) (result *RecordingsPage, err error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Passing a positive page returns the server's first page, not the requested page, across every paginated Everything method. Add page to the initial request query (for example via a request editor) or document/remove this parameter rather than promising a page-specific result.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At go/pkg/basecamp/everything.go, line 169:

<comment>Passing a positive page returns the server's first page, not the requested page, across every paginated Everything method. Add `page` to the initial request query (for example via a request editor) or document/remove this parameter rather than promising a page-specific result.</comment>

<file context>
@@ -0,0 +1,437 @@
+// Messages returns every message across all accessible projects, newest-first.
+// Pass a positive page to return only that page; page 0 follows the Link header
+// across all pages.
+func (s *EverythingService) Messages(ctx context.Context, page int32) (result *RecordingsPage, err error) {
+	op := OperationInfo{Service: "Everything", Operation: "Messages", ResourceType: "recording", IsMutation: false}
+	ctx, done, err := s.begin(ctx, op)
</file context>

Comment thread typescript/src/client.ts
defineService("tools", () => new ToolsService(client, hooks, fetchPage, maxPages));
defineService("timesheets", () => new TimesheetsService(client, hooks, fetchPage, maxPages));
defineService("timeline", () => new TimelineService(client, hooks, fetchPage, maxPages));
defineService("everything", () => new EverythingService(client, hooks, fetchPage, maxPages));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: EverythingService is wired into the client (import, type declaration, defineService) but not re-exported from index.ts, so it is missing from the package's public API surface. All other services in the codebase are re-exported — please add a re-export block for EverythingService (and any newly exported types like EverythingFile) to index.ts following the same pattern.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At typescript/src/client.ts, line 411:

<comment>EverythingService is wired into the client (import, type declaration, `defineService`) but not re-exported from `index.ts`, so it is missing from the package's public API surface. All other services in the codebase are re-exported — please add a re-export block for `EverythingService` (and any newly exported types like `EverythingFile`) to `index.ts` following the same pattern.</comment>

<file context>
@@ -405,6 +408,7 @@ export function createBasecampClient(options: BasecampClientOptions): BasecampCl
   defineService("tools", () => new ToolsService(client, hooks, fetchPage, maxPages));
   defineService("timesheets", () => new TimesheetsService(client, hooks, fetchPage, maxPages));
   defineService("timeline", () => new TimelineService(client, hooks, fetchPage, maxPages));
+  defineService("everything", () => new EverythingService(client, hooks, fetchPage, maxPages));
   defineService("clientVisibility", () => new ClientVisibilityService(client, hooks, fetchPage, maxPages));
   defineService("boosts", () => new BoostsService(client, hooks, fetchPage, maxPages));
</file context>

* const result = await client.everything.everythingFiles();
* ```
*/
async everythingFiles(options?: EverythingFilesEverythingOptions): Promise<components["schemas"]["GetEverythingFilesResponseContent"]> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: everythingFiles is paginated at runtime, but the declared return type is a plain array response alias. Using ListResult<...> in the signature preserves typed access to pagination metadata and matches the method’s actual return contract.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At typescript/src/generated/services/everything.ts, line 182:

<comment>`everythingFiles` is paginated at runtime, but the declared return type is a plain array response alias. Using `ListResult<...>` in the signature preserves typed access to pagination metadata and matches the method’s actual return contract.</comment>

<file context>
@@ -0,0 +1,273 @@
+   * const result = await client.everything.everythingFiles();
+   * ```
+   */
+  async everythingFiles(options?: EverythingFilesEverythingOptions): Promise<components["schemas"]["GetEverythingFilesResponseContent"]> {
+    return this.requestPaginated(
+      {
</file context>

type EverythingFile struct {
ID int64 `json:"id,omitempty"`
Status string `json:"status,omitempty"`
VisibleToClients bool `json:"visible_to_clients,omitempty"`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: False API values are lost when callers marshal EverythingFile. Keep JSON tags on these response booleans without omitempty so false is represented.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At go/pkg/basecamp/everything.go, line 62:

<comment>False API values are lost when callers marshal `EverythingFile`. Keep JSON tags on these response booleans without `omitempty` so `false` is represented.</comment>

<file context>
@@ -0,0 +1,437 @@
+type EverythingFile struct {
+	ID               int64     `json:"id,omitempty"`
+	Status           string    `json:"status,omitempty"`
+	VisibleToClients bool      `json:"visible_to_clients,omitempty"`
+	CreatedAt        time.Time `json:"created_at,omitempty"`
+	UpdatedAt        time.Time `json:"updated_at,omitempty"`
</file context>

ID int64 `json:"id,omitempty"`
Status string `json:"status,omitempty"`
VisibleToClients bool `json:"visible_to_clients,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Attachment variants with no timestamps serialize zero-time sentinels instead of preserving field absence. Use *time.Time for optional timestamps and populate them only when the generated value is present/non-zero.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At go/pkg/basecamp/everything.go, line 63:

<comment>Attachment variants with no timestamps serialize zero-time sentinels instead of preserving field absence. Use `*time.Time` for optional timestamps and populate them only when the generated value is present/non-zero.</comment>

<file context>
@@ -0,0 +1,437 @@
+	ID               int64     `json:"id,omitempty"`
+	Status           string    `json:"status,omitempty"`
+	VisibleToClients bool      `json:"visible_to_clients,omitempty"`
+	CreatedAt        time.Time `json:"created_at,omitempty"`
+	UpdatedAt        time.Time `json:"updated_at,omitempty"`
+	Title            string    `json:"title,omitempty"`
</file context>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

go kotlin ruby Pull requests that update the Ruby SDK spec Changes to the Smithy spec or OpenAPI swift typescript Pull requests that update TypeScript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants