build: bump openapi-generation to license token validation; elect the commercial license - #2124
build: bump openapi-generation to license token validation; elect the commercial license#2124ThomasRooney wants to merge 13 commits into
Conversation
|
Running ultrareview automatically — High-risk licensing change: wiring the CLI to the new license-token validation changes AGPL vs commercial election across all generation paths; a missed bug could mislicense outputs or break authenticated runs.. I'll post findings when complete. |
There was a problem hiding this comment.
Ultrareview completed in 7m 55s
All reported issues were addressed across 6 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
…2126) Dependency bump only, split out of #2124 so the SDK/core change ships and is verified on its own before the generator change. - `speakeasy-client-sdk-go/v3` v3.28.0 → **v3.28.1** (regenerated from the registry spec after speakeasy-registry#4708: `AccessDetails` gains `license_jwt` and `status_code`; no signature changes). - `speakeasy-core` v0.23.0 → **v0.24.0** (`access.CheckGenerationAccess` returns the full access decision including the platform-issued license token; `HasGenerationAccess` unchanged). No CLI behaviour change: nothing reads the token yet. #2124 (generator pin + commercial-on-token wiring) rebases on top once openapi-generation#55 is released. Guards from #2121 still apply: `internal/sdk/sdk_test.go` asserts `x-api-key` on `Artifacts.PostTags`/`GetRevisions`; `TestRegistryFlow` ends with `tag promote`. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Bumps `speakeasy-core` to v0.24.0 and `speakeasy-client-sdk-go/v3` to v3.28.1. These upgrades expose a platform-issued license token and new `AccessDetails` fields (`license_jwt`, `status_code`), but nothing reads them yet, so CLI behavior is unchanged. <sup>Written for commit 943cae8. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/speakeasy-api/speakeasy/pull/2126?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
5dbba26 to
07519df
Compare
There was a problem hiding this comment.
All reported issues were addressed across 6 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 13 files (changes from recent commits).
Tip: instead of fixing issues one by one fix them all with cubic
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 17 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 15 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
588a056 to
532bfa2
Compare
There was a problem hiding this comment.
2 issues found across 15 files (changes from recent commits).
Confidence score: 2/5
internal/model/command.goconflates--forceforrunandgenerate sdkwith an authentication refresh, causing valid offline licenses to be bypassed; keep generation forcing separate from authentication refresh handling.internal/auth/auth.goreturns an SDK-less context for valid offline-token users on everyRequiresAuthcommand, sostatus,billing activate, and configure can fail despite valid credentials; ensure offline authentication supplies the required SDK context or narrowly scopes the restriction.
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="internal/auth/auth.go">
<violation number="1" location="internal/auth/auth.go:74">
P2: When a valid offline token is used without an API key, `CommandContext` returns an SDK-less context for every `RequiresAuth` command. Commands such as `status`, `billing activate`, and configure then fail with a missing-API-key error instead of authenticating online; restrict this path to offline-capable commands or ensure platform authentication before online commands.
(Based on your team's feedback about SDK-less offline command contexts.)</violation>
</file>
<file name="internal/model/command.go">
<violation number="1" location="internal/model/command.go:140">
P1: When `--force` is used on `run` or `generate sdk`, this treats the generation-control flag as an authentication refresh request and bypasses valid offline licenses. Keep generation force separate from authentication refresh, using a dedicated auth-refresh signal instead.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
8c57c76 to
ba6ef5c
Compare
There was a problem hiding this comment.
All reported issues were addressed across 17 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 8 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
… commercial license Bumps openapi-generation/v2 to v2.934.0 (offline license validation with target-scoped tokens) and generation-context to v1.1.0 (WithDirect no longer implies AGPL; the election is explicit). Every generation elects the commercial license and attaches the license token from the platform access check (AccessDetails.license_jwt), falling back to the token in the authenticated context. The generator validates the token offline; an absent token is rejected as an unproven commercial election and the CLI warns that the platform may need updating. There is no AGPL election in the CLI. The workflow-level and lint dry-run AGPL/direct elections are removed; lint's dry-run elects commercial and skips a target's diagnostics when no generation context can be built (unauthenticated lint).
2c8c154 to
66c9824
Compare
…y-run diagnostics Removing the workflow-level election left run-path validation stamping a direct generation state onto authenticated contexts, which made GetSDKFromContext report unauthenticated and degraded link shortening. Validation now elects authenticated commercial when the caller is authenticated and falls back to direct OSS mode otherwise. Lint logs a debug line when a target's dry-run diagnostics are skipped instead of dropping them silently.
|
Possible regression: the workflow code-samples fallback loses its generation context. With the workflow-level election removed from The pre-rendered branch ( |
A hung CLI child consumed the whole suite's 30m budget and the suite timeout discarded the child's output. Each quickstart and run invocation now gets its own 10m deadline and reports the captured output when it expires.
…t fallback Removing the workflow-level election left runCodeSamples' fallback branch (GenerateOverlay -> usagegen -> Generate) without generation-access state: sdkgen.Generate's election is local to that call. The exported WithCommercialGenerationContext establishes the same commercial election with the context's license token, and lint's dry-run reuses it.
|
Confirmed and fixed in 5655b00 — the fallback branch of |
There was a problem hiding this comment.
All reported issues were addressed across 4 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
The token resolved during generation may come from the access check rather than the caller's context; runTarget now places it on the context so the code-samples fallback validates with the same token the generation did.
With recent generations in the workspace event stream, useRemoteSource defaulted to true and selectRecentGeneration ran its interactive picker even under --skip-interactive, blocking forever on a piped stdin. This is what intermittently hung the Windows quickstart integration tests: the shared CI workspace's telemetry from other runs made recent generations appear. Non-interactive quickstarts now always take the sample/local spec flow.
The validate call and the access check issue the same license token, so the resolved token no longer travels through GenerationAccess and the workflow context, and the no-token warning is dropped — an absent token surfaces as the generator's unproven-commercial rejection.
3aefe55 to
df17f46
Compare
The PR body's lint claim is wrong: the unproven-license error is swallowed, not surfaced. In runDryRunGeneration, g.Generate's errors are explicitly ignored (_ = errs, cmd/lint/lint.go ~line 625) and the unproven-commercial error is returned as an error before any warnings are produced, so g.GetWarnings() is empty. Authenticated-with-no-token lint silently yields zero dry-run diagnostics (it does not put the error "in the target's warnings" as the body states). Worth either surfacing that specific error or correcting the PR description. A bad license_jwt now breaks validation/lint too, not just generation. --> Intentional?? |
The platform now mints license tokens from /v1/auth/validate for free tiers as well (speakeasy-registry#4709), so the authenticated context's token is authoritative and the access check's token no longer needs to be preferred.
93d1529 to
2cd9b57
Compare
…dry runs; keep validation token-free generate codeSamples and generate usage called the generator with no generation-access state and failed with ErrMissingGenerationAccess (also broken on main); both now elect through WithCommercialGenerationContext. Lint's dry run reports a generation that failed before producing any warnings instead of presenting the target as clean. Validation no longer attaches the license token: it produces no licensed output, and an invalid token must not fail read-only diagnostics.
An unauthenticated --dry-run printed "No SDK generation warnings found" after skipping every target; the summary now names the skipped targets instead of presenting them as clean.
|
All three points verified and addressed in 9fa4bc7 (e2e-tested locally against prod with a built binary, sandboxed
PR body updated to match. One e2e side-note: the full flow validated speakeasy-registry#4709 end to end — online auth persisted the validate-issued token as |
There was a problem hiding this comment.
All reported issues were addressed across 1 file (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
The skip summary hardcoded "authentication required", mislabeling schema-load and generation failures; it now carries each target's error.
|
Two issues in the latest commits: 1.
Preferring 2. That option defaults to true only for newly-bootstrapped SDKs (its |
A test bootstrap rewrote the fixture with newSDK defaults (idiomaticMethodCollisionNames: true would rename collision fields on the next generation from this config); no generated source is committed here, so the config returns to main's state.
Why
main, the paid-tier "not in the approved SDK target list" warn path has produced AGPL-stamped output since the generation-context change.What Changed
Dependencies:
openapi-generation/v2v2.933.1 → v2.934.0 (offline license validation with target-scoped tokens),generation-contextv1.0.0 → v1.1.0 (WithDirectno longer implies AGPL; the election is explicit). Usesspeakeasy-corev0.24.0 (access.CheckGenerationAccessexposingAccessDetails.license_jwt) andspeakeasy-client-sdk-go/v3v3.28.1, already onmain.internal/sdkgen.withGenerationContext) and attaches the authenticated context's license token; the generator validates signature, expiry, and target coverage offline./v1/auth/validateissues the token for every tier (speakeasy-api/speakeasy-registry#4709: commercial["*"]at 30d, free["*"]at 24h), so the context token is authoritative and the access check's token is not consulted.Level == blocked) aborts before generation, unchanged.main: the paid-tier warn path produces commercial output again. Free workspaces get commercial output for their one language; a second language is blocked by the access check.lint --dry-runelects commercial with the context's token. A dry run that fails before producing any warnings (unauthenticated, or a rejected election) skips that target, and the summary names the skipped targets instead of reporting "no warnings found".generate codeSamplesandgenerate usage— dead onmain(ErrMissingGenerationAccess, no generation state ever established) — now elect through the same helper: they work when authenticated and fail with a clear "unauthenticated" error otherwise.internal/runperforms no election of its own (the workflow-level AGPL/direct election is removed); election happens ininternal/sdkgen. Validation elects authenticated commercial for authenticated callers (keeping SDK access, e.g. link shortening) and direct OSS mode otherwise; it attaches no license token, since it produces no licensed output and an invalid token must not fail read-only diagnostics.Rollout prerequisite: the deployed platform must issue
license_jwtfrom/v1/auth/validatefor every allowed tier before this ships — a platform that authenticates without issuing a token now produces a hard generator rejection (unproven commercial election) wheremainfell back to AGPL. Hosted prod satisfies this as of speakeasy-api/speakeasy-registry#4709 (deployed); older self-hosted/staging registries are the population at risk.Follow-up: #2127 adds offline license authentication on top of this.
Testing
go build ./...; unit suite (excludingintegration) green; golangci-lint clean on touched packages.internal/sdkgen/generation_context_test.go).$HOMEduring development: speakeasy-selfrun→ commercial output, no warning. Free workspacerun -t go→ commercial output;run -t typescript→ "Upgrade Required … exceeded the limit of one free generated SDK", blocked.