Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
2b1f868
Add experimental contract-generated ordinary API methods
kvz Sep 25, 2026
4d59577
Sync legacy package documentation and mark generated output
kvz Sep 25, 2026
30cb880
Address native contract transport review and extend HTTP canaries
kvz Sep 25, 2026
0f854b1
Merge remote-tracking branch 'origin/main' into sdk-contract
kvz Sep 27, 2026
f8f2a22
Improve generated API ergonomics and verify strict packed consumers
kvz Sep 27, 2026
0fa3951
Ship and strictly verify version-matched SDK workflow examples
kvz Sep 27, 2026
f9647ea
Preserve generated model exports and omit maintainer-only package met…
kvz Sep 27, 2026
9f49f05
Derive generated client signature options from the public contract
kvz Sep 27, 2026
91d3805
Handle omitted auth metadata and terminal Assembly aborts
kvz Sep 27, 2026
a9b5c9d
Keep generated contract packages within edge bundle budgets
kvz Sep 27, 2026
85c40ff
Normalize repeated trailing endpoint separators
kvz Sep 27, 2026
498ee8b
Exercise shared SDK workflows and enforce in-flight polling deadlines
kvz Sep 28, 2026
15dbee6
Honor SDK deadlines during retry backoff and adapt fractional timeouts
kvz Sep 28, 2026
7b6329d
Publish stable domain types in the draft contract client
kvz Sep 28, 2026
e849579
Address contract example, polling cleanup and packaging review
kvz Sep 28, 2026
1e9256c
Preserve cancellation error types during retry backoff
kvz Sep 28, 2026
25e2df8
Add owner-aware contract-client Assembly wait and cancellation workflows
kvz Sep 29, 2026
851711d
Release per-request abort listeners after workflow polling
kvz Sep 29, 2026
70614b1
Handle workflow backoff and terminal cancellation races safely
kvz Sep 29, 2026
35cabd5
Handle nullable terminal errors and trusted IPv6 uploaders
kvz Sep 29, 2026
be0e97d
Merge remote-tracking branch 'origin/main' into sdk-contract
kvz Sep 29, 2026
79d643d
Add bounded contract-client upload and fresh-client resume
kvz Sep 29, 2026
67058a2
Regenerate the legacy package upload documentation
kvz Sep 29, 2026
e002ddf
Honor upload deadlines and bounded recovery semantics
kvz Sep 29, 2026
50b659d
Distinguish connection loss from completion and recover safe progress
kvz Sep 29, 2026
a6139f9
Recover timed-out transfers and reconcile exact finished upload receipts
kvz Sep 29, 2026
88ec0f3
Preserve upload recovery outcomes and explicit proxy admission
kvz Sep 29, 2026
67c9ce9
Treat aborted requests as finite workflow outcomes
kvz Sep 29, 2026
f721d4b
Merge remote-tracking branch 'origin/main' into sdk-contract
kvz Sep 29, 2026
d505396
Regenerate finite workflow outcomes and cancellation failure contract
kvz Sep 29, 2026
2c29613
Synchronize generated wrapper workflow documentation
kvz Sep 29, 2026
49420a6
Clarify generated workflow deadlines and uploader admission
kvz Sep 29, 2026
6b03c5b
Merge current SDK main into experimental contract client
kvz Oct 4, 2026
8e31cf4
Verify source-owned upload identity and finished receipts
kvz Oct 4, 2026
bb5a2e4
Harden contract workflow identity and ambiguous-response recovery
kvz Oct 4, 2026
5821d95
Preserve caller aborts and cancellation confirmation diagnostics
kvz Oct 4, 2026
795ef0c
Preserve caller abort identity across fetch failures
kvz Oct 4, 2026
c4c3f41
Retain HTTP backoff and invalid cancellation confirmation diagnostics
kvz Oct 4, 2026
6269ccd
Merge remote-tracking branch 'origin/main' into sdk-contract
kvz Oct 6, 2026
c558bf7
Read future Assembly errors through contract workflows
kvz Oct 6, 2026
05b900c
Bound upload cleanup and preserve resumable workflow context
kvz Oct 6, 2026
af76fa4
Share bounded response cleanup and retain generated error hints
kvz Oct 6, 2026
8b01606
Preserve permanent fetch failures in contract workflows
kvz Oct 6, 2026
d63d6cc
Retain canary cleanup until processing succeeds
kvz Oct 6, 2026
6aa7faf
Honor grant-specific account authentication
kvz Oct 6, 2026
71196f2
Treat unset authentication options as absent
kvz Oct 6, 2026
56f4559
Keep redirect assertions in awaited tests
kvz Oct 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .changeset/contract-ordinary-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
'@transloadit/node': minor
'@transloadit/mcp-server': patch
'transloadit': minor
---

Add contract-generated ordinary HTTP methods through `client.contract()` and the `/contract`
entrypoint. The new methods support signed requests or explicit
bearer authentication. Token exchanges use the generated grant-specific account-authentication policy.
The standalone client can explicitly select `authentication: { kind: 'none' }` for public grants;
protected calls still require credentials. Login, storage and automatic refresh remain application-owned.
Add explicit `waitForAssembly` and `cancelAndWaitForAssembly` workflows over
these methods, with source-owned uploader admission, overall deadlines and terminal-status checks.
Cancellation is one attempt on the owning uploader, never an automatically retried write.
Add fixed-size `uploadAssemblyFile` and `resumeAssemblyFile` workflows through contract-owned tus
bindings. Persist a private upload session before bytes are sent; a fresh client checks the file
digest and server offset before resuming. Recover ambiguous PATCH responses without duplicating
accepted bytes. Creation never retries. Deferred lengths and concatenation remain outside this
experimental namespace.
Workflow status reads retry transient network failures and HTTP 429/5xx within the overall deadline,
honoring `Retry-After`. Waiting returns `REQUEST_ABORTED` as a finite, unsuccessful typed outcome,
not an exception or proof that background work stopped. Explicit cancellation still reaches the
owner once. A later status GET can confirm completion after a failed cancellation, but a repeated
`REQUEST_ABORTED` does not hide that failure. No terminal response promises worker or billing cleanup.
Explicitly configured proxy prefixes and loopback endpoints remain supported.
Read future nonempty Assembly error codes as terminal failures through GET, wait, cancellation
confirmation and stopped-upload recovery. Preserve exact error values as structured data, without
including them in generated diagnostic messages. Unknown success states and malformed status
discriminants remain invalid. An exact saved receipt proves only file transfer, not processing success.

Generated public types retain source documentation. Optional-only params can be omitted, JSON
response objects fit the exported `JsonValue`, and `ContractResponseError.code` exposes recognized
public error codes without leaking response content into messages. Add a typed end-to-end example
and strict packed-package compilation, including the root entry point's Robot declarations.

Add shared executable workflow fixtures for contract-client upload/resume/wait/cancel and local
Smart CDN signing. Keep ordinary regression coverage for the existing public SDK. Fix its polling deadline to
abort in-flight status requests and rate-limit retry waits, and reject late success responses as
`POLLING_TIMED_OUT`, instead of waiting past the caller's budget. This also applies when
`createAssembly` or `resumeAssemblyUploads` shares its remaining timeout with completion polling.
An already exhausted completion budget, including an explicit zero polling timeout, rejects before
the first status request instead of performing one last poll.
The `contract()` adapter rounds
positive fractional millisecond timeouts up to the next integer rather than rejecting them.
It rejects an inherited zero request timeout rather than silently changing it to an unbounded
request. In-flight legacy polling aborts retain got's `AbortError` classification; the polling
deadline still uses `PollingTimeoutError`.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/packages/node/src/generated-contract/* linguist-generated=true
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ jobs:
node-version: 22
- run: corepack yarn install --immutable
- run: corepack yarn run pack
- run: corepack yarn test:contract-package
- uses: actions/upload-artifact@v7
with:
name: package
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ packages/types/src/generated
packages/zod/src/v3
packages/zod/src/v4
packages/transloadit/src
packages/transloadit/examples/contract-workflow.ts
packages/transloadit/README.md
packages/transloadit/CHANGELOG.md
packages/transloadit/LICENSE
Expand Down
3 changes: 2 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"!.vscode",
"!packages/**/dist",
"!packages/**/node_modules",
"!packages/node/src/alphalib"
"!packages/node/src/alphalib",
"!packages/node/src/generated-contract"
]
},
"formatter": {
Expand Down
152 changes: 152 additions & 0 deletions docs/prompts/2026-09-29-contract-finality.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Contract workflow finality follow-up for #517

October 6 reader compatibility, still draft and unmerged:

- [x] Integrate main and reproduce future-error rejection before changing the workflow reader.
- [x] Regenerate from API2 producer `98c3d25a8f`; error admission comes from its public response
schema, not a duplicate finite list. Preserve raw codes as data and generic stop diagnostics.
- [x] Pass all 160 shared reader/mode observations, 447 focused tests and the full check
(1,353 Node cases, one existing skip, plus other workspace suites). Both packed package names
pass strict installed-consumer compilation. Receipts: `studio1:/tmp/sdk-readers.c3epZn/`.
- [x] Finish the first combined council. Reproduce then repair buffered-clone cleanup hanging past
request/workflow deadlines, saved custom field-name loss on resume, and the executable
example skipping cancellation after `REQUEST_ABORTED`. All 111 focused cases pass. Retain
HTTP status/backoff and caller precedence; the Go-equivalent cases are repaired too. Final
full `yarn check` passes (1,359 Node cases, one existing skip); both packed names compile.
- [ ] Finish the post-fix council, refreshed producer pins/runtime acceptance and exact-head CI.
- [x] The next council reproduced the same cloned-cleanup hang at ordinary redirect/size guards.
Four fail-first request/workflow-deadline cases now pass using the shared native cleanup
helper; all 171 focused cases pass. Fix the example fixture path portably. Regenerate from
producer `f8947685ba`, which restores TypeScript autocomplete and honest reader proof status.
- [x] Reproduce six permanent-fetch retry failures, including a native loopback redirect. Preserve
the original failure instead of replacing it with workflow timeout; only known transient
Node causes retry. Cause-less fetch TypeErrors remain recoverable for opaque/custom fetch
implementations. All 298 focused transport/lifecycle/tus cases pass, including 11 transient
cause controls. Repeat full checks, immutable runtime pins and the combined council.
- The previous combined council could not inspect remote API2 from one reviewer's sandbox.
That is incomplete producer evidence; use a checksummed immutable source archive for the rerun,
not a new checkout or changed authentication/sandbox settings.
- [x] The source-access-verified rerun reproduces the runtime canary removing cleanup ownership
before asserting `ASSEMBLY_COMPLETED`. The actual canary now retains ownership after
`REQUEST_ABORTED`; its fail-first test observes one cancellation instead of zero. This is
separate from the already repaired executable example. Broader timeout-default, known-value
hint and platform-portability suggestions were not retained as defects by the arbiter;
OAuth remains the explicit release blocker.
- Explicit next-slice merge blocker: current main's public `authorization_code` and `refresh_token`
grants need no Basic credentials, but the draft operation projection/transport requires them.
Fix this from the producer's grant-specific auth model before release; do not hand-patch generated
clients, borrow credentials, or hide the gap by accepting a bearer-configured Basic request.
- No release, merge, additional credentialed test or deployment. The canonical living document
remains API2's `docs/prompts/2026-07-09-handover-sdks-branch-restructure.md`.

October 4 final confirmation/tus correction, still draft and unmerged:

- [x] Complete the combined source-access-verified council. A P2 cloned-response cleanup timeout
discarded tus HTTP status/backoff; a P3 invalid confirmation body discarded the failed
DELETE diagnostic in both SDKs. Seventeen Node and two Go fail-first failures reproduce
these defects before changing implementation.
- [x] Treat confirmation reading and inspection as one failure boundary. Keep active/aborted
confirmation behavior and caller/deadline precedence; never repeat cancellation.
- [x] Retain tus HTTP failure status/backoff and request-timeout cause across body cleanup, while
explicit caller/workflow cancellation still wins. Nine POST/HEAD/PATCH and 403/429/503
cases plus three cloned-body caller-abort controls pass. All 287 focused cases pass.
- [x] Full post-fix `yarn check` passes: 1,180 Node tests with one existing skip, plus remaining
monorepo suites. The generated legacy wrapper README is synchronized mechanically.
- [ ] Repeat packed consumers; freeze sources, refresh producer pins, repeat local API2/tusd
acceptance and post-fix council, then monitor exact-head CI. Final receipts supersede this
pre-push snapshot; no merge, release or additional live-reader budget.

October 4 final diagnostics review, still draft and unmerged:

- [x] Source-access-verified combined council found a pre-header abort-identity defect. Four
fail-first tests reproduce a caller's `TypeError` being wrapped before or during fetch,
both with and without the SDK's own request timeout. The already-aborted case uses native
fetch against a loopback endpoint and sends no network request.
- [x] Reconcile explicit caller/workflow cancellation once at the transport rejection boundary.
Preserve HTTP status/backoff for SDK-owned request timeouts and detach request listeners.
All 265 focused native/shared workflow cases pass after the repair.
- [x] Full post-repair `yarn check` passes: 1,158 Node tests and one existing skip, plus the
remaining monorepo suites. No generated-client bytes or existing API shapes changed.
- [ ] Repeat both strict packed consumers; freeze the native commit and refresh the producer pin.
Re-run local API2/tusd proof, post-fix council and exact-head CI. Completion receipts belong
in the PR and canonical living record; these pending boxes are the pre-push snapshot.

October 4 identity follow-up, still draft and unmerged:

- [x] Merge current main and regenerate from the integrated API2 contract.
- [x] Reproduce malformed Base64, invalid UTF-8 and extra-token acceptance before changing decoding.
- [x] Consume source-owned tus identity grammar and receipt roles; compare owned values as bytes.
- [x] All 26 shared metadata/receipt cases and 101 focused tests pass, as does full `yarn check`.
- [ ] Complete both strict packed consumers, updated source-pin/local runtime proof, fresh council
and exact-head CI. Historical acceptance below does not certify this candidate.

October 4 council corrections, still draft and unmerged:

- [x] Reproduce broken error-body backoff and lost cancellation-response confirmation before fixes.
Preserve received HTTP status/delay and original causes; never repeat DELETE, and never hide
its error behind active or `REQUEST_ABORTED` confirmation.
- [x] Execute all 32 shared metadata/receipt cases, including repeated header fields, empty-file
counts and a normalization alias that must not count as an admitted receipt. The alias case
failed in Node before correction and passed in Go.
- [x] Restrict 409 recovery to tus, not ordinary Assembly discovery, with a failing test first.
- [x] Document proxy receipt rewriting and simple upload-ID restrictions, and explicitly describe
legacy zero/exhausted polling budgets in the changeset. Generate public return annotations
and structural tus policy conformance from API2, not by editing generated TypeScript.
- [x] Full `yarn check` passes: 1,140 Node tests pass, with one existing skip. Both packed consumers
pass strict installed compilation after retrying a transient registry socket failure.
- [x] Freeze `bb5a2e4391`, refresh API2 pins and pass the actual local API2/tusd canary. Exact-head
CI `37186698130`, attempt 2, is green; only an external Edge image-download quota failure
was retried. Healthy combined council accepts two P3 diagnostics findings, not the later repairs.
- [x] Reproduce caller-abort masking and lost DELETE diagnostics before fixes. Preserve caller-abort
identity and retain both failed DELETE and confirmation GET in
`AggregateError`; caller cancellation and the overall deadline still win. Focused tests pass.
- [x] A follow-up three-case regression reproduces lost HTTP status/backoff if the SDK's own request
timeout wins after receiving error headers. Keep that timeout as the HTTP error cause; only
explicit caller/workflow cancellation wins outright. Go already preserves both properties.
- [x] Full post-repair `yarn check` passes: 1,154 Node tests pass, with one existing skip. Both
caller-abort-during-confirmation controls and Go's mirrored cause/deadline checks pass.
- [ ] Freeze the new candidate, update producer pins/runtime proof and
complete the fresh post-fix council and exact-head CI. Earlier green heads are not approval.

The receipt-field follow-up below is historical: fields now come from API2's Status owner through
the contract. The deployed raw parser, legacy SDK APIs and live-reader resource budgets are unchanged.

Why: runtime investigation distinguished a finite client outcome from backend cleanup. The user
approved returning typed `REQUEST_ABORTED` from ordinary waiting, while still attempting explicit
cancellation and preserving a failed cancellation request. This is not merge/release approval.

- [x] Read PR context; no outstanding review threads. Preserve existing SDK APIs and native tus safety.
- [x] Reproduce the new lifecycle cases against the old implementation before changing it.
- [x] Implement finite ordinary wait, explicit cancel after an aborted connection, and preservation
of a failed DELETE when a later GET still reports `REQUEST_ABORTED`.
- [x] Merge latest main, including the Viewer changes and release; immutable install passes.
- [x] Regenerate from committed API2 producer `f13c20fe24`; generated contract SHA-256
`a72c65901795052a96036a2fa6beed7ac1885299fb3d6dfec8a011e2efc6f819`.
- [x] All 216 focused native/shared tests and full `yarn check` pass. Both packed package names
pass strict installed-consumer compilation, including exact optional properties and no
skipped declaration checks. The workstation Yarn wrapper selects Node 26; CI covers its
configured runtime matrix separately.
- [x] Exact-head CI on `2c29613e2ad2651399a5c632ca5569b5d3de7da7`: all 11 checks pass in
run `36625686355`, including the Edge fixture and Node 20/22/24. The previous registry quota
failure and stale generated wrapper README are resolved on this head.
- [x] Triage the completed Opus report: synchronize the generated wrapper, document that uploader
origins are additive, and explain that upload deadlines include hashing and persistence.
Correct the PR's claim that legacy behavior is unchanged: the separately tested polling
deadline repair also affects `createAssembly` and `resumeAssemblyUploads`. The changeset
already describes that behavior change.
- [ ] Complete multi-model council. This attempt's Codex reviewer and arbiter hit provider quota;
the Opus report alone is not council approval. Retry when capacity is available.
- [ ] Post-documentation checks and exact-head CI.

Review dispositions: preserving the synchronous `client.contract()` API requires its runtime
dependency; a dynamic import would change that API. Most generated source is erased types, so
source-file size is not an import-cost measurement. Keep the opt-in subpath and existing root
compile checks. This checklist is maintainer documentation, not shipped API/schema prose. Receipt
field names remain an explicit next producer-policy follow-up, with real-server receipt acceptance
already covered; do not duplicate that inventory in another test adapter.

Canonical program history and cross-repository receipts remain in API2's
`docs/prompts/2026-07-09-handover-sdks-branch-restructure.md` on `sdk-next`.
No new live credentialed tests, merge or release in this follow-up.

https://github.com/transloadit/node-sdk/pull/517
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@
"pack": "node scripts/pack-transloadit.ts",
"parity:transloadit": "node scripts/prepare-transloadit.ts && node scripts/fingerprint-pack.ts packages/transloadit --ignore-scripts --quiet --out /tmp/transloadit-after.json && node scripts/verify-fingerprint.ts --current /tmp/transloadit-after.json --diff",
"test:img:fixture": "node scripts/test-img-next-fixture.ts",
"test:contract-package": "node scripts/test-contract-package.ts",
"test:sdk:edge": "node scripts/test-sdk-edge.ts",
"test:unit": "vitest run ./scripts/withProcess.test.ts ./scripts/img-next-fixture.test.ts ./scripts/knip.test.ts ./scripts/publish-release.test.ts ./scripts/release-run.test.ts ./scripts/sdk-edge.test.ts && yarn workspace @transloadit/utils test:unit && yarn workspace @transloadit/viewer test:unit && yarn workspace @transloadit/node test:unit && yarn workspace @transloadit/mcp-server test:unit && yarn workspace @transloadit/types test:unit && yarn workspace @transloadit/zod test:unit && yarn workspace @transloadit/notify-url-relay test:unit",
"test:unit": "vitest run ./scripts/withProcess.test.ts ./scripts/img-next-fixture.test.ts ./scripts/knip.test.ts ./scripts/prepare-contract-dist.test.ts ./scripts/publish-release.test.ts ./scripts/release-run.test.ts ./scripts/sdk-edge.test.ts && yarn workspace @transloadit/utils test:unit && yarn workspace @transloadit/viewer test:unit && yarn workspace @transloadit/node test:unit && yarn workspace @transloadit/mcp-server test:unit && yarn workspace @transloadit/types test:unit && yarn workspace @transloadit/zod test:unit && yarn workspace @transloadit/notify-url-relay test:unit",
"test:types": "yarn workspace @transloadit/zod test:types",
"test:e2e": "yarn workspace @transloadit/node test:e2e",
"test": "yarn workspace @transloadit/node test",
"tsc:img": "yarn workspace @transloadit/viewer lint:ts",
"tsc:node": "yarn tsc:utils && node ./node_modules/typescript/bin/tsc -b packages/node/tsconfig.build.json && chmod +x packages/node/dist/cli.js",
"tsc:node": "yarn tsc:utils && node ./node_modules/typescript/bin/tsc -b packages/node/tsconfig.build.json && node scripts/prepare-contract-dist.ts && chmod +x packages/node/dist/cli.js",
"tsc:types": "yarn workspace @transloadit/types generate && node ./node_modules/typescript/bin/tsc -b packages/types/tsconfig.build.json",
"tsc:utils": "yarn workspace @transloadit/utils lint:ts",
"tsc:zod": "yarn workspace @transloadit/zod sync && node ./node_modules/typescript/bin/tsc -b packages/zod/tsconfig.build.json"
Expand Down
Loading
Loading