fix(tasks): keep resolved credentials out of queued job payloads, add credential schemes - #677
Conversation
|
Same for This PR touches Likely cause is contention: several PRs from this triage pass had CI running concurrently, each pulling the same models from the Hub. I'll re-run the failed job once the run finishes (GitHub refuses a re-run while it is still in progress). If it reproduces after a clean re-run I'll investigate further rather than assume flakiness. Generated by Claude Code |
Coverage Report
File CoverageNo changed files found. |
3fa31ac to
f8caa3c
Compare
FetchUrlTask resolved `credential_key` into the secret and wrote it as an `Authorization` header onto the same object handed to `registeredQueue.client.send(...)`. Queue bodies are persisted durably (SQLite/Postgres/SQS), so on the opt-in queued path the token was written to storage. The default inline path was unaffected. The queued path now refuses to run when a credential is present, rather than silently downgrading to the inline path — a downgrade would quietly drop the per-domain rate limiting the queue exists to provide. All three credential ports are stripped from the job input, so a resolved secret only ever exists as an in-process request header. Also adds credential scheme support so non-OAuth APIs work: `credential_scheme` (bearer | basic | header | none, default bearer, so existing graphs are unchanged) and `credential_header` for API-key style services. `basic` sends the secret verbatim as a pre-encoded user:pass blob. Header names are validated as bare header tokens to close a header-injection vector. Placement lives in the exported pure function `applyCredentialToHeaders`. Corrects the credential-management doc, which described a resolver miss as returning the reference string unchanged; the resolver deliberately returns undefined so a key's name is never sent as its value. Claude-Session: https://claude.ai/code/session_01PwyJuFrJnibKvrrk8Fa4Fn
HTTP header names are case-insensitive, so a caller-supplied `authorization` survived alongside the credential's `Authorization` and both were sent, leaking the caller's stale token. Claude-Session: https://claude.ai/code/session_01PwyJuFrJnibKvrrk8Fa4Fn
f8caa3c to
6181ed4
Compare
## @workglow/browser-control ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/task-graph ### Features - add tests for task usage duration and enhance usage line handling #### web-example - show the run's cumulative token total #### task-graph - add an opt-in run-usage recorder - report a cache hit as a stated zero cost - aggregate token usage per run - add a task-level usage event - fold mid-stream usage snapshots without double-counting - add the mid-stream usage event - ship InMemoryTaskOutputRepository from ./test ### Bug Fixes - improve usage tracking - usage tracking for owned subtasks in Task Graph #### ai,task-graph - keep heuristic usage estimates out of accounting #### task-graph - count an owned child's late charge once - scope usage sinks to the run that supplied them - drop the run_usage columns nothing can populate - roll usage up by task and by model, not one slice each - count a nested task's spend once, not once per hop - break the Task/ConditionalTask module cycle - detach the run's usage listeners at run end - reset the usage aggregator per run instead of replacing it - key usage buckets without string collision - defer the pipe-function wrapper past the Task cycle #### task-graph,ai - route a checkpoint's storage charge into the run total #### test - satisfy typecheck:tests across the usage test helpers - close the gaps the Turbo/projects wiring opened #### util - last complete object wins when skipping JSON preamble (#718) ### Refactors - decompose BaseTabularStorage.ts and Task.ts along functional seams (#682) #### task-graph - name run-usage columns like every sibling schema #### test - drop the FsFolderTaskOutputRepository shim ### Tests - run tests through Turbo and per-package vitest projects - move 174 more unit tests into their owning packages - discover test files instead of enumerating sections #### task-graph - cover the cache-hit usage emit - cover usage survival on aborted and finish-less streams - make the StreamUsage type assertion actually enforceable - relocate the remaining task-graph test infrastructure - move TestTasks into the package's ./test entry - extract the streaming task-output repository contract #### ai - pin the Usage field contract and assert disjointness ### Chores - upgrade to catalog for many deps and update the deps themselves #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/javascript ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/ai ### Features - enhance provisional usage reporting in AI provider streams - implement CLI duration formatting and enhance task usage tracking #### ai - add ModelConfig.effort coarse thinking dial - add a shared usage and cost formatter - charge checkpoint cache storage at disposal - add estimateCost over disjoint usage buckets - add optional per-model pricing to the model schema - fold usage snapshots in the accumulator and publish from AiTask - add a ./test entry and drop _testOnly from the public API #### providers - emit cumulative usage snapshots mid-stream ### Bug Fixes - improve usage tracking - make the ./test entries survive a real build #### ai,task-graph - keep heuristic usage estimates out of accounting #### task-graph,ai - route a checkpoint's storage charge into the run total #### ai - delete the CheckpointEntry fields nothing reads - attribute chat spend to the chat model - charge every checkpoint's storage cost, not just the last link - count the whole prompt in the usage arrow - keep checkpoint teardown from stranding registry entries - require explicit ModelPricing rates and make the type assertion enforceable - make the OpenAI-shaped usage mappers report disjoint input #### task-graph - detach the run's usage listeners at run end #### test - close the gaps the Turbo/projects wiring opened ### Tests - run tests through Turbo and per-package vitest projects - move 174 more unit tests into their owning packages #### ai - verify OpenAI cache counters are portions of input_tokens - drop the unused binding without gutting the pricing check - pin the cumulative detail level and the detailed cached counter - drop the non-falsifiable ModelPricing round-trip ### Chores - add Lezer dependencies and update Vite configuration #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/knowledge-base ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Tests - run tests through Turbo and per-package vitest projects ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## workglow ### Features #### ai - add a ./test entry and drop _testOnly from the public API ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Documentation #### build - correct the surviving bun-condition count and pin it with a test (#716) ## @workglow/storage ### Features #### storage - enhance query operators to support null handling and inequality checks ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Refactors - decompose BaseTabularStorage.ts and Task.ts along functional seams (#682) ### Tests - run tests through Turbo and per-package vitest projects - move 174 more unit tests into their owning packages ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/mcp ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Tests - run tests through Turbo and per-package vitest projects - settle the Bun policy, close a CI gap, and pilot the __tests__ move ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/util ### Features #### util - add a ./test entry and drop _testOnly from the public API ### Bug Fixes - reunite the graph test helper with its dependents - make the ./test entries survive a real build #### util - last complete object wins when skipping JSON preamble (#718) - resolve repo-root script imports independently of the vitest root - stop TestingLogger inlining a second ConsoleLogger #### test - close the gaps the Turbo/projects wiring opened ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Tests - run tests through Turbo and per-package vitest projects - move 174 more unit tests into their owning packages - settle the Bun policy, close a CI gap, and pilot the __tests__ move - discover test files instead of enumerating sections ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/test ### Features - enhance model existence verification in AI provider streams - enhance provisional usage reporting in AI provider streams - dd prefill phase emission to HFT streaming #### models - update pricing and add new model for DeepSeek #### anthropic - honor model.effort for extended/adaptive thinking #### deepseek - map model.effort to reasoning_allowance #### openrouter - map model.effort into reasoning extras #### openai - map model.effort to Responses reasoning #### hft - report local token counts as usage, not a phase message #### gemini - report checkpoint write tokens and cache lifetime - add support for reproducible generation with sampling seed #### providers - report cache-checkpoint warm-up token cost - emit cumulative usage snapshots mid-stream #### storage - enhance query operators to support null handling and inequality checks #### task-graph - ship InMemoryTaskOutputRepository from ./test #### ai - add a ./test entry and drop _testOnly from the public API #### util - add a ./test entry and drop _testOnly from the public API ### Bug Fixes - improve usage tracking - usage tracking for owned subtasks in Task Graph - reunite the graph test helper with its dependents - make the ./test entries survive a real build #### huggingface-inference - forward provider-stated usage from text run-fns - encode Hub model ids per path segment #### anthropic - keep an in-range top_p under legacy extended thinking - build a legal request under legacy extended thinking #### ai,task-graph - keep heuristic usage estimates out of accounting #### task-graph - count an owned child's late charge once - scope usage sinks to the run that supplied them - count a nested task's spend once, not once per hop - break the Task/ConditionalTask module cycle - key usage buckets without string collision #### gemini - remove structured-generation 2048 thinking default - return cache disposal result through the queued path - report disjoint input and fold thoughts into output #### tasks - handle the SafeFetch body-pipe rejection instead of crashing the process - keep resolved credentials out of queued job payloads, add credential schemes (#677) #### task-graph,ai - route a checkpoint's storage charge into the run total #### test - satisfy typecheck:tests across the usage test helpers - update provider-api usage expectations to the disjoint contract - guard against getAll() returning undefined in PostgresTabularDateTime test #### deepseek - map the stated cache-miss count to disjoint input #### ai - make the OpenAI-shaped usage mappers report disjoint input #### job-queue - retry promptly when an idle peek finds a ready job ### Refactors - decompose BaseTabularStorage.ts and Task.ts along functional seams (#682) #### tests - streamline model info test function calls (fix type errors) #### test - drop the FsFolderTaskOutputRepository shim #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Tests - fix out of date assertion in test - run tests through Turbo and per-package vitest projects - delete the unused Postgres task-output and task-graph repositories - move 174 more unit tests into their owning packages - settle the Bun policy, close a CI gap, and pilot the __tests__ move - discover test files instead of enumerating sections - add unit tests for OpenAI reasoning and temperature coupling, and Postgres date handling #### huggingface-inference - pin the estimate/stated boundary for HFI #### ai - verify OpenAI cache counters are portions of input_tokens - pin the Usage field contract and assert disjointness #### task-graph - cover a nested task's spend reaching the run total - relocate the remaining task-graph test infrastructure - move TestTasks into the package's ./test entry - extract the streaming task-output repository contract #### providers - drop a plan reference from a test comment - cover checkpoint warm-up usage wiring #### storage - exercise a null criterion against a real index ### Documentation #### build - correct the surviving bun-condition count and pin it with a test (#716) ### Chores - update deps - add Lezer dependencies and update Vite configuration - upgrade to catalog for many deps and update the deps themselves - update deps #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ### Updated Dependencies - `@aws-sdk/client-sqs`: catalog: - `@cloudflare/workers-types`: catalog: - `@types/dom-chromium-ai`: catalog: - `@types/pg`: catalog: - `aws-sdk-client-mock`: catalog: - `fake-indexeddb`: catalog: - `miniflare`: ^5.20260811.0-alpha - `vitest`: catalog: ## @workglow/tasks ### Bug Fixes #### tasks - handle the SafeFetch body-pipe rejection instead of crashing the process - keep resolved credentials out of queued job payloads, add credential schemes (#677) #### test - close the gaps the Turbo/projects wiring opened ### Chores - update deps #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ### Updated Dependencies - `ipaddr.js`: ^2.5.0 - `undici`: ^8.10.0 ## @workglow/job-queue ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened #### job-queue - retry promptly when an idle peek finds a ready job ### Refactors #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Tests - run tests through Turbo and per-package vitest projects - move 174 more unit tests into their owning packages ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/indexeddb ### Features #### storage - enhance query operators to support null handling and inequality checks ### Bug Fixes #### indexeddb - keep a null equality criterion out of IDBKeyRange #### test - close the gaps the Turbo/projects wiring opened ### Refactors #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Chores - upgrade to catalog for many deps and update the deps themselves #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ### Updated Dependencies - `fake-indexeddb`: catalog: ## @workglow/openai ### Features - enhance model existence verification in AI provider streams - enhance provisional usage reporting in AI provider streams #### openai - map model.effort to Responses reasoning #### providers - report cache-checkpoint warm-up token cost ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Tests - add unit tests for OpenAI reasoning and temperature coupling, and Postgres date handling ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/llamacpp-server ### Features - enhance usage tracking in AI providers ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable ## @workglow/electron ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ## @workglow/ollama ### Features - enhance provisional usage reporting in AI provider streams ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/node-llama-cpp ### Features - enhance usage tracking in AI providers ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/aws ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Refactors #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Chores - upgrade to catalog for many deps and update the deps themselves - update deps ### Updated Dependencies - `@aws-sdk/client-sqs`: catalog: - `aws-sdk-client-mock`: catalog: ## @workglow/anthropic ### Features - enhance model existence verification in AI provider streams #### anthropic - honor model.effort for extended/adaptive thinking #### providers - report cache-checkpoint warm-up token cost - emit cumulative usage snapshots mid-stream ### Bug Fixes #### anthropic - keep an in-range top_p under legacy extended thinking - build a legal request under legacy extended thinking #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Refactors #### tests - streamline model info test function calls (fix type errors) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/duckdb ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/google-gemini ### Features - enhance model existence verification in AI provider streams #### gemini - map model.effort to thinking_budget - report checkpoint write tokens and cache lifetime - add support for reproducible generation with sampling seed #### ai - charge checkpoint cache storage at disposal #### providers - emit cumulative usage snapshots mid-stream ### Bug Fixes #### gemini - remove structured-generation 2048 thinking default - return cache disposal result through the queued path - report disjoint input and fold thoughts into output #### ai - keep checkpoint teardown from stranding registry entries - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/postgres ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Refactors #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Tests - add unit tests for OpenAI reasoning and temperature coupling, and Postgres date handling ### Chores - upgrade to catalog for many deps and update the deps themselves - update deps #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ### Updated Dependencies - `@types/pg`: catalog: ## @workglow/stable-diffusion-server ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable ## @workglow/supabase ### Features #### storage - enhance query operators to support null handling and inequality checks ### Bug Fixes #### supabase - keep deleteSearch's filter builder off the generic path #### test - close the gaps the Turbo/projects wiring opened ### Refactors #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/xai ### Features - enhance model existence verification in AI provider streams - enhance provisional usage reporting in AI provider streams #### models - update pricing and add new model for DeepSeek ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/deepseek ### Features - enhance model existence verification in AI provider streams - enhance provisional usage reporting in AI provider streams #### models - update pricing and add new model for DeepSeek #### deepseek - map model.effort to reasoning_allowance ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### deepseek - map the stated cache-miss count to disjoint input #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/playwright ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ## @workglow/sqlite ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Refactors #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/cloudflare ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ### Refactors #### job-queue - collapse per-backend queue adapters onto wrapQueueStorage (#684) ### Chores - upgrade to catalog for many deps and update the deps themselves - update deps ### Updated Dependencies - `@cloudflare/workers-types`: catalog: ## @workglow/huggingface-transformers ### Features - dd prefill phase emission to HFT streaming #### hft - report local token counts as usage, not a phase message ### Bug Fixes - better error message when HFT has issues importing #### task-graph - count a nested task's spend once, not once per hop #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### HFT_Device - remove "webgpu" from device resolution logic #### util - last complete object wins when skipping JSON preamble (#718) ### Refactors - update @huggingface/transformers to peerDependency and add to devDependencies ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores - upgrade to catalog for many deps and update the deps themselves #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/tf-mediapipe ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/chrome-ai ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Tests - discover test files instead of enumerating sections ### Chores - upgrade to catalog for many deps and update the deps themselves #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ### Updated Dependencies - `@types/dom-chromium-ai`: catalog: ## @workglow/openrouter ### Features - enhance model existence verification in AI provider streams #### openrouter - map model.effort into reasoning extras ### Bug Fixes - improve usage tracking #### ai - require explicit ModelPricing rates and make the type assertion enforceable #### util - last complete object wins when skipping JSON preamble (#718) ### Performance #### util - add an incremental partial-JSON stream parser (#681) ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/huggingface-inference ### Features - enhance model existence verification in AI provider streams - enhance provisional usage reporting in AI provider streams ### Bug Fixes #### huggingface-inference - forward provider-stated usage from text run-fns - encode Hub model ids per path segment #### ai - require explicit ModelPricing rates and make the type assertion enforceable ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/cactus ### Bug Fixes #### ai - require explicit ModelPricing rates and make the type assertion enforceable ### Tests - discover test files instead of enumerating sections ### Chores #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ## @workglow/bun-webview ### Bug Fixes #### test - close the gaps the Turbo/projects wiring opened ## @workglow/eval ### Features #### models - update pricing and add new model for DeepSeek #### eval-example - record and rank token usage and cost ### Bug Fixes #### eval - price the gpt-5.6 family, drop the bogus Anthropic max_tokens ### Tests - run tests through Turbo and per-package vitest projects #### eval-example - cover the token-accounting logic the crux review flagged ### Documentation #### eval-example - stop the rate card asserting a provenance it lacks ### Chores - update CodeMirror dependencies and improve TypeScript configuration - upgrade to catalog for many deps and update the deps themselves ### Updated Dependencies - `commander`: catalog: - `hyparquet`: ^1.28.1 ## @workglow/cli ### Features - add tests for task usage duration and enhance usage line handling - implement CLI duration formatting and enhance task usage tracking #### cli-example - show live input and output token counts ### Bug Fixes - usage tracking for owned subtasks in Task Graph #### cli-example - render token usage on the actual rendered path #### ai - require explicit ModelPricing rates and make the type assertion enforceable ### Refactors #### pricing - optimize model pricing state management and improve usage line updates #### cli-example - hoist the footer's format call and drop a needless cast ### Tests - run tests through Turbo and per-package vitest projects #### cli-example - gate usage emission on a mounted row, not a fixed sleep ### Chores - update deps - update CodeMirror dependencies and improve TypeScript configuration - upgrade to catalog for many deps and update the deps themselves #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ### Updated Dependencies - `commander`: catalog: - `react`: catalog: - `smol-toml`: ^1.8.0 - `@types/react`: catalog: ## @workglow/web ### Features #### web-example - show the run's cumulative token total ### Bug Fixes - improve usage tracking #### task-graph,ai - route a checkpoint's storage charge into the run total #### task-graph - roll usage up by task and by model, not one slice each ### Chores - untrack examples/web/tsconfig.norefs.tsbuildinfo - update deps - add Lezer dependencies and update Vite configuration - update CodeMirror dependencies and improve TypeScript configuration - upgrade to catalog for many deps and update the deps themselves - update deps #### eslint - enforce consistent-type-imports and apply the repo-wide autofix (#683) ### Updated Dependencies - `@xyflow/react`: ^12.11.3 - `react`: catalog: - `@types/react`: catalog: - `vite`: ^8.2.1
Fixes the two remaining defects in
FetchUrlTask's credential handling. The broader credential subsystem (ICredentialStore, the stores,CREDENTIAL_STORE, theformat: "credential"resolver path, AI credential resolution) was already shipped and is unchanged here — see the now-closed #238.Security defect (#673)
FetchUrlTaskresolvedcredential_keyinto the real secret and wrote it as anAuthorizationheader onto the same object that was then handed to the queue:A source comment claimed the credential was stripped "so the secret is not persisted to queue storage". It stripped the
credential_keyfield but not the header it had just written. Queue bodies are persisted durably (SQLite / Postgres / SQS), so the bearer token was written to storage.Scope: the opt-in queued path only (
config.queuetruthy). The default inline path (queue ?? false) never reached the queue and was not affected.Behavior chosen
The queued path now refuses to run when a credential is present, raising a
TaskConfigurationError:Explicit refusal rather than a silent downgrade to the inline path — a downgrade would quietly drop the per-domain rate limiting that is the whole reason a caller asks for a queue. Resolving the credential inside
FetchUrlJob.execute()was rejected as the alternative: run-fns execute in workers with a separateglobalServiceRegistry, so touching a credential store there violates the worker-isolation rule in CLAUDE.md.All three credential ports are now stripped from the job input unconditionally, so a resolved secret only ever exists as an in-process request header. The misleading comment is replaced with the real invariant.
Credential schemes (#674)
Authorization: Bearerwas hard-coded, so non-OAuth APIs could not use credential references. Added two plain non-secret config ports (onlycredential_keycarriesformat: "credential"):credential_schemebearer | basic | header | nonebearercredential_headerstringAuthorizationbearerremains the default, so this is not a breaking change.basicsends the secret verbatim as a pre-encodeduser:passbase64 blob — no splitting or encoding is invented here.headerplaces the raw secret incredential_headerfor API-key style services.credential_headeris validated as a bare header token (1–64 chars of letters, digits, hyphens); anything else raises aTaskConfigurationError. This rejects the CR/LF, colon and whitespace that would otherwise permit header injection. Validation runs even for schemes that ignore the field, so a malformed name is reported rather than silently discarded.Placement logic is extracted into the exported pure function
applyCredentialToHeaders()(packages/tasks/src/task/FetchUrlCredentials.ts) so it is unit-testable directly.Precedence decision: a resolved credential overwrites a same-named header supplied in
headers. The credential store is authoritative, and letting a hard-coded header shadow it would silently defeat the configured credential. This matches the previous behavior and is now asserted and documented.Docs (#673)
docs/technical/15-credential-management.mdclaimed that on a store miss "the resolver returns the original string unchanged". The code deliberately returnsundefined— echoing the id would thread the credential's name through as its value, sending the key name to the remote host in anAuthorizationheader and masking the misconfiguration. The doc now matches the code, and gains a section covering the new fields and the queue interaction.Tests
packages/test/src/test/task/FetchTask.test.tshad zero credential coverage. Added 12 tests usingInMemoryCredentialStoreon aServiceRegistryscoped to its ownContainer, plus direct unit tests of the pure function.Verification
The G1 regression test was written first and confirmed failing on unmodified
main. The failure shows the secret verbatim inside the persisted queue row:After the fix:
Not in scope
AWS Secrets Manager / HashiCorp Vault / GCP Secret Manager adapters are tracked separately in #675 and are not attempted here — three heavyweight SDKs with three auth models, untestable in CI, and no consumer in this repo currently needs them.
Closes #673
Closes #674
🤖 Generated with Claude Code
https://claude.ai/code/session_01PwyJuFrJnibKvrrk8Fa4Fn
Generated by Claude Code