Skip to content

Expand spec to 102 operations, regenerate all 5 SDKs#9

Merged
jeremy merged 5 commits into
mainfrom
serene-booth
Mar 9, 2026
Merged

Expand spec to 102 operations, regenerate all 5 SDKs#9
jeremy merged 5 commits into
mainfrom
serene-booth

Conversation

@jeremy

@jeremy jeremy commented Mar 8, 2026

Copy link
Copy Markdown
Member

Summary

  • 32 new operations added to the Smithy spec (102 total, was 70): access tokens, account settings, board entropy/involvement, join codes, notification settings, push subscriptions, search, steps index, user role management
  • 4 summary types removed (pre-1.0 breaking): UserSummaryUser, BoardSummaryBoard, ColumnSummaryColumn, PinCard
  • Go typed returns: generator resolves ResponseContent schemas to *generated.Type or []generated.Type
  • Idempotent POST retry: WithIdempotent(ctx) in Go, retryable: true kwarg in Ruby — driven from behavior-model.json
  • All 5 SDKs regenerated: Go, TypeScript, Ruby, Swift, Kotlin
  • Conformance: 111 tests across 9 fixtures, 4 runners (Go, TS, Ruby, Kotlin), all passing
  • RAILS-API-COMMUNIQUE.md: documents 28 JSON endpoints needed from Rails (implemented in Add JSON response format for full SDK/CLI coverage fizzy#2675)

Breaking changes

Pre-1.0 SDK — no public consumers. These would be semver-major post-1.0:

Change Impact
UserSummary deleted Use User instead
BoardSummary deleted Use Board instead
ColumnSummary deleted Use Column instead
Pin / PinList deleted ListPins returns Card / CardList
Tag.nameTag.title Field rename
NotificationCard.boardNotificationCard.board_name Field rename
New required fields on Account, Tag, NotificationCard Breaking for type constructors

Merge order

  1. Add JSON response format for full SDK/CLI coverage fizzy#2675 lands first (adds the 28 JSON endpoints the SDK expects)
  2. This PR merges after Rails deploys
  3. Integration test against staging to validate response shapes

Test plan

  • make check passes (Smithy, OpenAPI, behavior model, url-routes, provenance, rubric audit, all 5 SDK checks, all 4 conformance runners)
  • CI green on this branch
  • Rails api-breadth deployed to staging
  • SDK conformance run against live staging

Copilot AI review requested due to automatic review settings March 8, 2026 22:20

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.

Pull request overview

Expands the Fizzy OpenAPI/Smithy surface area to 102 operations and regenerates all 5 SDKs, including behavior-model–driven retry semantics and updated conformance infrastructure.

Changes:

  • Added many new operations and removed/renamed pre-1.0 summary types, regenerating Go/TypeScript/Ruby/Swift/Kotlin SDK outputs.
  • Introduced/standardized per-operation retry behavior (including idempotent POST retry) driven by behavior-model.json.
  • Expanded conformance fixtures/runners and refreshed CI/Make targets to enforce drift/freshness and security checks.

Reviewed changes

Copilot reviewed 74 out of 270 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
ruby/scripts/generate-services.rb Updates Ruby service generation (tag-less service derivation + behavior-model retry flags).
ruby/lib/fizzy/http.rb Adds retry override plumbing + tightens pagination origin error message + localhost HTTP exception.
ruby/lib/fizzy/errors.rb Ensures JSON dependency is available for error parsing/handling.
ruby/lib/fizzy/client.rb Plumbs retry override through client verbs; adds miscellaneous service accessor.
ruby/.rubocop.yml Disables Rails-specific Minitest cop for this non-Rails gem.
rubric-audit.json Updates rubric audit date and operation/test counts for 102 ops.
kotlin/sdk/src/commonTest/kotlin/com/basecamp/fizzy/FizzyTest.kt Adds Kotlin SDK tests for exception defaults, pagination SSRF guard, retry-after parsing, etc.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/services/BaseService.kt Adds root-scoped URL helpers + PATCH support; improves cross-origin pagination handling.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/http/FizzyHttpClient.kt Expands retryable status codes/methods and updates retry policy docs.
kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/FizzyHooks.kt Broadens hook IDs to support non-Long identifiers.
kotlin/generator/src/main/kotlin/com/basecamp/fizzy/generator/ServiceEmitter.kt Fixes PATCH emission and supports root-scoped operations.
kotlin/generator/src/main/kotlin/com/basecamp/fizzy/generator/OperationParser.kt Adds isAccountScoped + derives service names when tags are absent.
kotlin/generator/src/main/kotlin/com/basecamp/fizzy/generator/MetadataEmitter.kt Makes behavior-model retry parsing more tolerant of missing fields.
kotlin/generator/src/main/kotlin/com/basecamp/fizzy/generator/Config.kt Adds operationId-based service name derivation for untagged operations.
go/pkg/fizzy/webhooks_service.go New generated Go Webhooks service methods.
go/pkg/fizzy/users_service.go New generated Go Users service methods.
go/pkg/fizzy/url-routes.json Regenerated URL routes to cover new endpoints/params.
go/pkg/fizzy/uploads_service.go New generated Go Uploads service methods.
go/pkg/fizzy/tags_service.go New generated Go Tags service methods.
go/pkg/fizzy/steps_service.go New generated Go Steps service methods.
go/pkg/fizzy/sessions_service.go New generated Go Sessions service methods.
go/pkg/fizzy/search_service.go New generated Go Search service method.
go/pkg/fizzy/reactions_service.go New generated Go Reactions service methods.
go/pkg/fizzy/pins_service.go New generated Go Pins service method.
go/pkg/fizzy/operations_registry.go Adds operationId→service method registry for drift checking.
go/pkg/fizzy/notifications_service.go New generated Go Notifications service methods.
go/pkg/fizzy/identity_service.go New generated Go Identity service method.
go/pkg/fizzy/http.go Adds WithNoRetry / WithIdempotent context controls and updates retry docs.
go/pkg/fizzy/devices_service.go New generated Go Devices service methods.
go/pkg/fizzy/comments_service.go New generated Go Comments service methods.
go/pkg/fizzy/columns_service.go New generated Go Columns service methods.
go/pkg/fizzy/client.go Removes old generated OpenAPI client usage; adds PATCH; adds new services + retry/error mapping tweaks.
go/pkg/fizzy/cards_service.go New generated Go Cards service methods.
go/pkg/fizzy/boards_service.go New generated Go Boards service methods.
go/pkg/fizzy/api-provenance.json Updates provenance fields (but appears to diverge from spec provenance file copy).
go/pkg/fizzy/account_service.go New generated Go Account service methods.
go/pkg/fizzy/access_tokens_service.go New generated Go AccessTokens service methods.
go/oapi-codegen.yaml Switches Go codegen to types-only output.
go/go.mod Adds tooling and indirect deps needed for generation/diffing.
go/cmd/generate-services/main_test.go Adds tests for Go service generator typed returns and helpers.
go.work Adds workspace config with Go version pin.
conformance/tests/status-codes.json Adds new status-code fixtures for new operations.
conformance/tests/request-shapes.json Adds request-shape fixtures for new operations/fields.
conformance/tests/integer-precision.json Adds fixtures for large integer/string ID handling.
conformance/tests/idempotency.json Adds idempotent POST retry fixtures; updates PATCH/DELETE paths.
conformance/schema.json Extends conformance schema with new overrides and assertion types.
conformance/runner/typescript/vitest.config.ts Adds Vitest timeout config for TS runner.
conformance/runner/typescript/tsconfig.json Adds TS runner tsconfig.
conformance/runner/typescript/runner.test.ts Adds TS conformance runner using MSW + operation dispatcher.
conformance/runner/typescript/package.json Adds TS conformance runner package manifest.
conformance/runner/ruby/runner.rb Adds Ruby conformance runner using WebMock + operation dispatcher.
conformance/runner/ruby/Gemfile Adds Gemfile for Ruby conformance runner.
conformance/runner/go/go.mod Adds Go module for Go conformance runner.
behavior-model.json Expands operations and retry-on codes (adds 500) + idempotent markers.
SECURITY.md Documents cross-SDK security properties and retry/SSRF guarantees.
RAILS-API-COMMUNIQUE.md Documents required Rails JSON endpoints and response shape expectations.
Makefile Adds drift/freshness/provenance checks, splits check targets, and updates release/audit logic.
.pre-commit-config.yaml Adds pre-commit hooks including golangci-lint.
.github/workflows/test.yml Adds permissions, drift/freshness checks, splits conformance jobs, adds lint jobs, updates node versions.
.github/workflows/smithy-verify.yml Adds additional freshness checks and fixes $GITHUB_PATH/$GITHUB_OUTPUT quoting.
.github/workflows/security.yml Adds permissions, pins tool versions, adds Trivy/gosec jobs, updates node versions.
.github/workflows/release-typescript.yml Fixes $GITHUB_OUTPUT quoting.
.github/workflows/release-swift.yml Fixes $GITHUB_OUTPUT quoting.
.github/workflows/release-ruby.yml Uses find to select gem artifact deterministically.
.github/workflows/release-go.yml Fixes $GITHUB_OUTPUT quoting.
.github/workflows/release-github.yml Fixes $GITHUB_OUTPUT quoting.
.github/workflows/dependabot-auto-merge.yml Adds auto-merge workflow for Dependabot PRs.
.github/release.yml Adds release-note category configuration.
.github/prompts/spec-impact.prompt.yml Adds PR prompt to detect spec pipeline impact.
.github/actionlint.yaml Adds actionlint config stub.
Files not reviewed (1)
  • conformance/runner/typescript/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

.github/workflows/test.yml:1

  • go-version: '1.26' is likely not a valid Go release (as of the latest stable versions prior to Aug 2025). If this version doesn’t exist in actions/setup-go, CI will fail to install Go. Use an existing Go version (or a semver range supported by the action), and ensure go.work / module go directives match.
name: Test

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

Comment thread ruby/scripts/generate-services.rb
Comment thread go/pkg/fizzy/search_service.go
Comment thread go/pkg/fizzy/api-provenance.json
Comment thread kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/FizzyHooks.kt
Comment thread go/pkg/fizzy/access_tokens_service.go Outdated
Comment thread go/pkg/fizzy/access_tokens_service.go Outdated
Comment thread go/pkg/fizzy/access_tokens_service.go Outdated
Comment thread go/pkg/fizzy/http.go Outdated

@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.

15 issues found across 270 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

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="rubric-audit.json">

<violation number="1" location="rubric-audit.json:20">
P2: Criterion 1A.6 still references "All 70 operations" while 4B.5 now references 102. Update 1A.6's note to match the current operation count so the audit document is internally consistent.</violation>
</file>

<file name="go/cmd/generate-services/main.go">

<violation number="1" location="go/cmd/generate-services/main.go:749">
P1: String query parameter values are not URL-encoded. The generated code uses `fmt.Sprintf` with `%s` to interpolate string values directly into the URL. For `SearchCards`' `q` parameter, search terms containing spaces, `&`, `=`, or other reserved characters will produce a malformed URL. The generator should emit `url.QueryEscape(*value)` for string-typed query params (and add `"net/url"` to the import block).</violation>
</file>

<file name="scripts/check-rb-service-drift.sh">

<violation number="1" location="scripts/check-rb-service-drift.sh:23">
P2: `grep` returns exit code 1 when there are no matches. Under `set -euo pipefail`, this silently kills the script before it can report the drift. Prefix with `{ grep ... || true; }` so that zero matches produce empty output instead of aborting.</violation>
</file>

<file name="kotlin/conformance/src/main/kotlin/com/basecamp/fizzy/conformance/Main.kt">

<violation number="1" location="kotlin/conformance/src/main/kotlin/com/basecamp/fizzy/conformance/Main.kt:105">
P2: `skipped` is declared and printed in the summary but never incremented. Unsupported assertion types hit the `ASSERT SKIP` print path yet return `true`, so they count as passes and the summary always reports `0 skipped`.</violation>
</file>

<file name=".pre-commit-config.yaml">

<violation number="1" location=".pre-commit-config.yaml:16">
P3: Add `pass_filenames: false` — the `bash -c` entry ignores staged filenames, so pre-commit appends them for nothing. Making this explicit avoids confusion and a (minor) wasted argument-list construction on each commit.</violation>
</file>

<file name="go/pkg/fizzy/access_tokens_service.go">

<violation number="1" location="go/pkg/fizzy/access_tokens_service.go:11">
P3: Generator bug: `accesstoken` should be `access token` (two words). The resource name from `access_tokens` is concatenated instead of being split on underscore. Same issue on lines 24 and 29. Since this is generated code, the fix belongs in `go/cmd/generate-services/`.

(Based on your team's feedback about deriving doc comment subjects from the service resource and fixing the generator rather than generated code.) [FEEDBACK_USED]</violation>
</file>

<file name="conformance/runner/go/main.go">

<violation number="1" location="conformance/runner/go/main.go:145">
P3: Both `loadNoRetryOps` and `loadIdempotentPostOps` duplicate ~40 lines of identical file-reading and JSON-parsing logic, and `main()` calls them with the same paths — reading each file twice. Consider extracting a shared helper that parses both files once and returns both maps.</violation>

<violation number="2" location="conformance/runner/go/main.go:255">
P2: The `skipped` counter is declared but never incremented, so the summary always reports `0 skipped`. Meanwhile, unsupported assertion types in `checkAssertion` return `true` and are silently counted as passes. The Ruby runner handles this correctly by tracking per-test skip state — the Go runner should do the same so unknown assertion types don't inflate the pass count.</violation>
</file>

<file name="kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/services/BaseService.kt">

<violation number="1" location="kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/services/BaseService.kt:244">
P2: Cross-origin pagination link should silently break instead of throwing. Replace the throw with `break` so pagination stops quietly and `ListMeta.truncated` indicates incomplete results.

(Based on your team's feedback about silently stopping pagination on cross-origin links.) [FEEDBACK_USED]</violation>
</file>

<file name="kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/http/FizzyHttpClient.kt">

<violation number="1" location="kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/http/FizzyHttpClient.kt:201">
P3: Stale inline comment at line ~97 still lists `(GET, PUT, DELETE, HEAD)` — it should include PATCH to match the updated `IDEMPOTENT_METHODS` set and the updated KDoc above `requestWithRetry`.</violation>
</file>

<file name="scripts/check-ts-service-drift.sh">

<violation number="1" location="scripts/check-ts-service-drift.sh:23">
P2: With `set -euo pipefail`, `grep` returning no matches (exit 1) will crash the script instead of reporting drift. Wrap the `grep` so a no-match exit code doesn't propagate.</violation>
</file>

<file name="go/pkg/fizzy/boards_service.go">

<violation number="1" location="go/pkg/fizzy/boards_service.go:58">
P3: Generator bug: `"closeds"` is not a word. The `generateDocComment` function naively pluralises the method-name remainder, which breaks for adjective suffixes. This method returns `[]generated.Card`, so the comment should say something like "returns closed cards for a board." Fix in `go/cmd/generate-services/main.go`.</violation>
</file>

<file name="go/pkg/fizzy/notifications_service.go">

<violation number="1" location="go/pkg/fizzy/notifications_service.go:17">
P2: Generator produces ungrammatical doc comment `returns a settings` — "settings" is uncountable, so the article is wrong. Same issue on `UpdateSettings` (line 73). The root cause is in `go/cmd/generate-services/main.go` around line 694: when the derived resource is already plural/uncountable (like "settings"), the generator should omit the article (e.g. `returns notification settings`) or singularize correctly.

(Based on your team's feedback about fixing the generator rather than generated code.) [FEEDBACK_USED]</violation>
</file>

<file name="kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/FizzyHooks.kt">

<violation number="1" location="kotlin/sdk/src/commonMain/kotlin/com/basecamp/fizzy/FizzyHooks.kt:45">
P2: `Any?` is unnecessarily broad — every call site passes `String?`. Use `String?` to preserve type safety and give hook consumers a clear contract without needing casts.</violation>
</file>

<file name="RAILS-API-COMMUNIQUE.md">

<violation number="1" location="RAILS-API-COMMUNIQUE.md:135">
P2: Three operations listed here (`UnpublishBoard`, `MarkCardUnread`, `ReopenCard`) are DELETE, not POST, per the OpenAPI spec. Calling them "POST operations" is inaccurate and could mislead Rails implementers about the expected HTTP method. Consider rewording to "The SDK retries these operations…" and noting which are POST (idempotent-tagged) vs DELETE (retried by default).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread go/cmd/generate-services/main.go Outdated
Comment thread rubric-audit.json
Comment thread scripts/check-rb-service-drift.sh Outdated
Comment thread conformance/runner/go/main.go Outdated
Comment thread .pre-commit-config.yaml
Comment thread go/pkg/fizzy/access_tokens_service.go Outdated
Comment thread conformance/runner/go/main.go
Comment thread go/pkg/fizzy/boards_service.go Outdated

@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: 23df158741

ℹ️ 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 thread go/pkg/fizzy/search_service.go Outdated
Comment thread go/pkg/fizzy/search_service.go

@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.

1 issue found across 16 files (changes from recent commits).

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/fizzy/http.go">

<violation number="1" location="go/pkg/fizzy/http.go:24">
P3: The `MaxRetries` field comment now says "retryable requests," but the `WithMaxRetries` function doc on line 61 still says "idempotent requests." Update it to match.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread go/pkg/fizzy/http.go
Add 32 new operations covering access tokens, account settings,
board entropy/involvement, join codes, notification settings,
push subscriptions, search, steps index, and user role management.

Consolidate summary types (UserSummary→User, BoardSummary→Board,
ColumnSummary→Column, Pin→Card) across all SDKs — breaking for
pre-1.0 consumers that reference the removed types.

Go SDK gains typed return values and idempotent POST retry via
WithIdempotent(ctx). Ruby gains retryable: true kwarg. Both
propagated through generator from behavior-model.json.

Generator improvements: URL-encode string query params, CamelCase
word splitting in doc comments, smart pluralization, uncountable
noun handling. Conformance runner skipped counters now tracked.

Conformance suite expanded to 111 tests across 9 fixture files.
All 4 runners (Go, TS, Ruby, Kotlin) passing.
Copilot AI review requested due to automatic review settings March 8, 2026 23:05

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.

Pull request overview

Copilot reviewed 46 out of 129 changed files in this pull request and generated 2 comments.

Files not reviewed (2)
  • conformance/runner/typescript/package-lock.json: Language not supported
  • typescript/package-lock.json: Language not supported

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

Comment thread go/pkg/fizzy/url-routes.json
Comment thread RAILS-API-COMMUNIQUE.md Outdated
jeremy added 2 commits March 8, 2026 16:14
32 new generated service methods (thin wrappers over client HTTP
methods) expanded the statement count without adding per-method
tests. The underlying HTTP plumbing is well-tested; the generated
wrappers are validated by conformance tests, not unit tests.
Go URLRoute struct now matches the actual JSON schema (pattern/
operations/params wrapper). URLRouteByOperation searches the
operations map correctly.

Remove PublishCard and DeactivateWebhook from the idempotent retry
list in RAILS-API-COMMUNIQUE.md — neither is marked idempotent in
behavior-model.json.
Copilot AI review requested due to automatic review settings March 8, 2026 23:25

@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.

1 issue found across 2 files (changes from recent commits).

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="RAILS-API-COMMUNIQUE.md">

<violation number="1" location="RAILS-API-COMMUNIQUE.md:145">
P2: `DeactivateWebhook` is listed in the non-retry list but doesn't exist as an operation in the behavior model or anywhere in the codebase. If this operation was removed from the spec, drop it from this list to avoid confusing Rails developers about what endpoints the SDK actually calls.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread RAILS-API-COMMUNIQUE.md Outdated

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.

Pull request overview

Copilot reviewed 47 out of 130 changed files in this pull request and generated 1 comment.

Files not reviewed (2)
  • conformance/runner/typescript/package-lock.json: Language not supported
  • typescript/package-lock.json: Language not supported

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

Comment thread .github/workflows/test.yml
jeremy added 2 commits March 9, 2026 09:08
* Add permissions block to release-swift workflow

Declare explicit `contents: read` permissions to enforce
least-privilege and resolve code scanning alert #53.

* Add permissions block to smithy-verify workflow

Declare explicit `contents: read` permissions to enforce
least-privilege and resolve code scanning alert #55.

* Add permissions block to smoke workflow

Declare explicit `contents: read` permissions to enforce
least-privilege and resolve code scanning alert #59.
File was dropped during branch re-squash. Restored from prior commit
and removed DeactivateWebhook from non-retry list — the operation
doesn't exist in the spec.
@jeremy jeremy merged commit fe26755 into main Mar 9, 2026
39 checks passed
@jeremy jeremy deleted the serene-booth branch March 9, 2026 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants