Files
promptkit/docs/roadmap/audit/catalog.md

667 lines
38 KiB
Markdown

# Consolidated Pre-1.0 Audit Catalog
Consolidated on 2026-11-04 from the 11 audit documents in this directory.
Their 41 numbered findings are represented by 34 entries below. Entries that
describe the same underlying issue share one remediation scope; missing
regression coverage for an identified defect is included with that defect.
Some broad testing findings consequently support more than one entry.
The order reflects consequence, exposure, and the value of clarifying public
contracts before v1.0. Confirmed defects and conditional security exposure come
first, followed by contract/test gaps, resource efficiency, and maintainability.
This ordering does not upgrade the original severities or turn every cleanup
into a release gate. The source audits retain their evidence, qualifications,
and validation results. None of these entries is marked remediated by this
documentation-only consolidation.
## 1. Update The Audited Maintainer Toolchain For Applicable Security Fixes
**Conditional security exposure.** The audited Go 1.27.0 toolchain predates
networking fixes applicable to HTTP clients, including HTTP/2 CPU exhaustion
and conditional certificate-trust exposure. Use a patched maintainer toolchain
and repeat the focused security assessment against it. Actual downstream
exposure depends on the toolchain that builds the consumer and its transport
and trust configuration; raising PromptKit's minimum Go requirement is a
separate compatibility concern, not an implied remedy.
[Decision 5](#decision-5-consumer-go-minimum-after-the-toolchain-update) reaffirms
independent maintainer-toolchain selection and the initial-release consumer
minimum. Advising consumers about generally applicable Go vulnerabilities is
outside PromptKit's responsibility.
Sources: [Security 1](07-security.md#1-the-audited-go-toolchain-predates-applicable-networking-security-fixes).
## 2. Bound Authentication-Probe Response Consumption
**Confirmed resource/security defect.** Authentication diagnostics read a
successful upstream body with unbounded `io.ReadAll`. A deadline does not bound
the bytes a fast server can supply.
[Decision 3](#decision-3-authentication-response-budget-and-overflow-outcome)
selects a fixed 1 MiB internal constant and explicit overflow diagnostics, with
credential acceptance unknown. Implementation remains pending. Overflow should
not be interpreted as proof of rejected authentication.
Relocating the provider adapter in entry 26 would not itself fix this defect.
Sources: [Resources 1](05-resources.md#1-authentication-diagnostics-read-an-unbounded-upstream-body),
[Security 2](07-security.md#2-authentication-probes-permit-unbounded-remote-body-memory-consumption).
## 3. Avoid Exponential Expansion During Convenience Source Conversion
**Confirmed resource defect.** `ProfileSource` and `BackendSource` conversion
expand repeated references before ConfigKit performs its bounded snapshot.
A small shared acyclic graph can therefore cause exponential work and
allocation. [Decision 4](#decision-4-exact-numbers-and-the-source-conversion-boundary)
selects removal of the recursive compatibility adapter, passing ConfigKit-supported
values directly to its bounded snapshot. Do not add conversion memoization,
PromptKit-side raw-source limits, or duplicate ConfigKit validation. Cover direct
handoff, source ownership, and deferred unsupported/cyclic-value diagnostics for
both helpers. Implementation remains pending.
Sources: [Resources 2](05-resources.md#2-convenience-source-conversion-expands-shared-graphs-before-bounded-loading),
[Testing 3](08-testing.md#3-programmatic-provider-value-conversion-lacks-representative-value-cases).
## 4. Resolve The ArtifactReader Buffer-Ownership Contract
**Confirmed race under the documented collaborator contract.** The public
reader contract permits buffer reuse after `Read` returns, before PromptKit
can finish copying it. Concurrent preparation with a compliant custom reader
can race. [Decision 1](#decision-1-artifactreader-result-ownership-and-lifetime)
selects ownership transfer on successful return; implementation remains pending.
Align adapters, GoDoc, and concurrency tests with that rule. An immediate copy
alone cannot guarantee safety under the old immediate-reuse permission. No
default-reader defect was established.
Sources: [Interfaces 1](09-interfaces.md#1-artifactreader-permits-buffer-reuse-before-promptkit-can-copy-it).
## 5. Preserve Exact Numbers In Programmatic Provider Sources
**Confirmed data-integrity defect.** Convenience source conversion falls back
from integer parsing to `float64` without checking precision, silently changing
some accepted `json.Number` values.
[Decision 4](#decision-4-exact-numbers-and-the-source-conversion-boundary) selects
removal of this conversion, not a new exact-number subsystem. Convenience-source
provider values must use ConfigKit-supported types; callers choose any necessary
conversion. Let ConfigKit report unsupported values during loading. Cover supported
value handoff and rejection of formerly converted unsupported types without adding
numeric precision guarantees. Runtime overrides remain a separate input path.
Sources: [Correctness 1](01-correctness.md#1-provider-source-helpers-silently-change-exact-json-numbers),
[Testing 3](08-testing.md#3-programmatic-provider-value-conversion-lacks-representative-value-cases).
## 6. Make Provider-Native Schema Constraints Self-Contained
**Confirmed implementation gap; self-contained schemas selected.** Local
validation freezes referenced schema resources, but the provider receives only
the root document and cannot resolve its local external references.
[Decision 2](#decision-2-provider-submission-of-multi-resource-schemas) selects
self-contained schema documents and removal of external-resource loading.
Reject references requiring another document during preparation with an
actionable error; retain references within the selected document. Add coverage
for early rejection and for self-contained schemas reaching the provider intact.
Implementation remains pending. Entry 21 is a separate compilation refactor;
coordinate it with this simplification rather than preserving unnecessary
external-resource machinery.
Sources: [Correctness 2](01-correctness.md#2-external-schema-resources-do-not-reach-the-provider-constraint),
[Testing 5](08-testing.md#5-multi-resource-schema-tests-do-not-establish-a-usable-provider-constraint).
## 7. Preserve The Owning Operation's Public Error Category
**Confirmed classification defect.** Public error conversion searches nested
causes in a global priority order, allowing a collaborator's sentinel to hide
the enclosing operation's category. Map the owning boundary independently
while retaining the original cause for `errors.Is`/`errors.As`. Add composed
cause regressions; simply reordering global checks can break legitimate direct
not-found versus load-failure distinctions. Carry explicit owning-operation
information through translation. Retaining nested causes may legitimately make
multiple public categories match through `errors.Is`; the remedy preserves the
owning category rather than requiring category exclusivity.
Sources: [Error handling 1](06-error-handling.md#1-nested-collaborator-errors-can-hide-the-owning-operations-public-category),
[Testing 4](08-testing.md#4-error-tests-miss-composed-causes-and-pre-dispatch-diagnostic-failures).
## 8. Distinguish Response Stream Failures From Malformed JSON
**Confirmed error-handling defect.** Non-context I/O failures while decoding a
successful HTTP response or checking its end are reported as malformed JSON,
losing the transport cause; complete JSON followed by a read failure can also
be misreported as trailing data. Retain and classify reader failures separately
using the existing redacted transport boundary. Preserve cancellation
precedence and genuine malformed/truncated/oversized-content handling. Cover
both read locations without adding transport retries.
Sources: [Error handling 2](06-error-handling.md#2-successful-status-body-read-failures-are-misreported-as-malformed-json),
[Testing 4](08-testing.md#4-error-tests-miss-composed-causes-and-pre-dispatch-diagnostic-failures).
## 9. Return Invalid Diagnostic Request Construction As A Go Error
**Confirmed diagnostic-contract defect.** Some invalid inference settings fail
before dispatch yet produce a completed report with a nil Go error. Propagate
local request-construction failures through `ErrInvalidRequest` and add a
no-dispatch regression. Preserve intentionally completed diagnostic outcomes
for missing credentials, capacity outcomes, and unsupported or inapplicable
operations; not every no-dispatch outcome is invalid configuration.
Use explicit preparation-stage failure information rather than inferring the
stage from a sentinel alone or from an empty attempt list.
Sources: [Error handling 3](06-error-handling.md#3-inference-diagnostics-swallow-some-invalid-request-construction-errors),
[Testing 4](08-testing.md#4-error-tests-miss-composed-causes-and-pre-dispatch-diagnostic-failures).
## 10. Remove Quadratic Requirement-Evidence Union Work
**Confirmed algorithmic inefficiency.** A left-heavy recognized condition can
repeatedly copy growing missing-key evidence sets, producing quadratic work.
Use operation-local accumulation or ownership-aware merging while preserving
classification and conservative inspection coverage. Do not address this by
adding expression limits or expanding the recognized template language. Entry
23's traversal cleanup is related but is not a substitute for fixing this
specific accumulation algorithm.
Sources: [Efficiency 1](02-efficiency.md#1-condition-evidence-unions-can-require-quadratic-work).
## 11. Exercise RunRequest's Privacy Formatting Boundary
**Missing protection, not a demonstrated leak.** Request formatting methods
have no execution coverage despite owning a privacy-sensitive public boundary.
Add focused tests with distinct synthetic private markers for the relevant
value/pointer formatting paths and JSON omission behavior. Assert privacy and
the documented boundary, not an incidental complete diagnostic or JSON shape.
Sources: [Testing 1](08-testing.md#1-runrequests-privacy-formatting-contract-is-not-exercised).
## 12. Correct Profile Inspection Credential Documentation
**Public-contract documentation defect.** Inspection GoDoc incorrectly makes
required credentials and an environment variable mutually exclusive. Actual
behavior permits an explicit profile environment variable while suppressing
only the backend-derived default when required credentials are selected.
Correct the field/method GoDoc and consumer example, keeping the established
configuration behavior and DTO shape.
Sources: [Interfaces 2](09-interfaces.md#2-profile-inspection-misstates-required-credential-semantics).
## 13. Correct The Configured Provider-Map Wire Documentation
**Integration-contract documentation defect.** The wire document says backend
and profile provider maps replace one another, but configuration recursively
overlays them; runtime replacement is a separate rule. Align the integration
summary with the canonical format reference rather than maintaining a second
conflicting precedence definition. Entry 19 concerns the efficiency of the
existing overlay, not a change to its semantics.
Sources: [Interfaces 3](09-interfaces.md#3-the-wire-contract-incorrectly-says-configured-provider-maps-replace).
## 14. Remove Stale Identity And Version GoDoc
**Public-contract documentation defect.** Inspection comments still describe
trimmed profile IDs, and listing comments describe a removed prompt-version
field. Update them to the implemented literal identity and current collection
version model. Do not normalize meaningful whitespace or reintroduce a field
to match obsolete comments.
Sources: [Interfaces 4](09-interfaces.md#4-identity-godoc-still-describes-removed-normalization-and-version-fields).
## 15. Cover The Public Single-Schema-File Option
**Public wiring coverage gap.** Direct filesystem-validator tests do not
exercise `WithSchemaFile` through engine construction. Add offline temporary
file cases through public preparation/validation, including option precedence
and relevant file errors. This is a supported feature, not dead code; entry
32 removes only an unused private helper result.
Sources: [Testing 2](08-testing.md#2-the-public-single-schema-file-option-has-no-execution-coverage).
## 16. Detach Inert Prepared Handles From The Execution Owner
**Avoidable retention.** Used or discarded prepared handles retain their
runner, and therefore the engine's captured configuration and collaborators.
Use a narrower ownership identity or clear the unnecessary owner reference
safely. Preserve foreign-owner rejection, one-time claim, namespace-view
behavior, and available details. This is unnecessary retention when a handle
outlives its engine, not evidence of an ever-growing global leak.
Prefer a small standalone ownership token that preserves identity after
use/discard without retaining the runner graph. Its distinct identity must not
depend on zero-sized allocations comparing unequal. If clearing the owner
pointer instead, synchronize the currently unlocked ownership check with that
mutation and preserve ownership/state behavior under concurrent claim/discard.
Sources: [Resources 3](05-resources.md#3-inert-prepared-handles-retain-their-entire-execution-owner).
## 17. Bound Repair Feedback's Temporary Serialization
**Avoidable peak allocation.** Feedback formatting serializes potentially
large diagnostic text before truncating the final message, so its existing
output bound does not bound scratch memory. Produce bounded encoded feedback
incrementally, preserving the existing output semantics and complete stored
validation diagnostics and previous candidate. A new raw-diagnostic input
limit is not implied.
Use representative allocation measurements for large and heavily escaped
diagnostics to assess the remedy, alongside the existing output-behavior tests.
Keep the encoder proportionate; the output bound does not establish an exact
peak-heap guarantee or justify a general-purpose encoding framework.
Sources: [Resources 4](05-resources.md#4-repair-feedbacks-output-bound-does-not-bound-its-temporary-serialization).
## 18. Detach Normalized Session IDs From Large Input Strings
**Avoidable retention.** A short trimmed session ID can retain the allocation
of a much larger padded caller string. Clone the accepted normalized value at
its ownership boundary. Preserve trimming, accepted content, code-point
validation, and resulting wire/hash content rather than adding a raw-input
size restriction.
Sources: [Resources 5](05-resources.md#5-short-normalized-session-ids-can-pin-large-input-strings).
## 19. Avoid Repeated Descendant Cloning During Provider Overlay
**Construction-time inefficiency.** Recursive overlays repeatedly clone and
sort overlapping descendant maps, giving work proportional to tree size times
depth. Existing depth bounds mean this is not unbounded quadratic growth.
Clone ownership once or use a single traversal while retaining recursive-map,
null, and array semantics. Coordinate with entry 24 without assuming all JSON
walkers have interchangeable policies.
Compare representative nested overlays before and after the change for
allocation/work reduction. Balance the measured benefit against implementation
complexity, preserving input isolation instead of removing necessary copies.
Sources: [Efficiency 2](02-efficiency.md#2-recursive-provider-overlay-repeatedly-clones-descendant-subtrees).
## 20. Index Filtered Listings By Namespace
**Repeated inspection overhead.** Filtered listing currently copies and scans
the complete inventory even when few or no entries match. Capture namespace
buckets or equivalent ranges so queries operate on the relevant subset.
Preserve ordering, exact identity matching, cancellation, and caller-owned
results. A pagination API or runtime cache is not needed for this improvement.
Evaluate representative namespace counts and match sizes, including absent
namespaces, and account for additional construction cost and retained indexing
memory. Choose buckets or ranges based on that tradeoff. These measurements and
those for entries 17 and 19 inform the changes; they add no performance contract
or recurring release gate.
Sources: [Efficiency 3](02-efficiency.md#3-filtered-listings-copy-and-scan-the-complete-inventory).
## 21. Share Schema Compilation And Declare The Runner's Real Dependency
**Maintainability and interface clarity.** Four host-file/`fs.FS`,
direct/prepared paths repeat the schema compilation lifecycle. The runner also
declares a validator interface while requiring preparation through a runtime
assertion. Share the lifecycle behind source-specific adapters and make that
dependency explicit. Preserve malformed-output short-circuiting before schema
I/O, source containment, exact numbers, cancellation, and frozen plans. Retain
independent cross-source tests; do not force whole entry points to be identical.
Sources: [Complexity 1](03-complexity.md#1-consolidate-schema-compilation-and-express-the-runners-actual-interface),
[Equivalence 1](10-equivalence.md#1-share-the-schema-compilation-lifecycle-across-source-and-execution-paths).
## 22. Decompose Configuration Validation And Materialization
**Maintainability.** Large configuration operations mix record-specific
validation, resource capture, and effective-profile construction. Extract
focused helpers with visible inputs and ownership, rather than another generic
validation framework. Preserve final-handoff validation, presence/null rules,
origins, and meaningful fail-fast/error-precedence behavior. Do not turn
incidental ordering of independent validation failures into a new guarantee.
The configuration-boundary ADR remains authoritative; this is not a proposal
to inspect raw ConfigKit sources.
Sources: [Complexity 2](03-complexity.md#2-decompose-configuration-validation-and-resource-materialization).
## 23. Clarify Requirement Traversal And Share Branch Orchestration
**Maintainability.** Separate recognition/evaluation from reachability and
evidence bookkeeping, particularly the repeated `if`/`with` branch protocol.
Keep their scope differences explicit and retain independent comparisons with
the actual Go renderer. Preserve conservative partial coverage and inactive
computed-name behavior. This does not justify a general template interpreter
or stronger execution-readiness promises from requirements inspection.
Sources: [Complexity 3](03-complexity.md#3-untangle-requirement-traversal-expression-evaluation-and-evidence),
[Equivalence 3](10-equivalence.md#3-share-ifwith-requirement-branch-orchestration-not-template-execution).
## 24. Centralize Compatible JSON Copying Without Conflating Policies
**Maintainability and ownership clarity.** The facade maintains a separate
reflection traversal for already-normalized values despite an existing
`internal/jsonvalue` owner. Consolidate genuinely compatible structural
copying while retaining DTO projection at the facade and distinct source
encoding/runtime validation policies. Preserve concrete types, nils, exact
numbers, schema keys, and ownership. Infallible projection must not acquire
new errors, panics, or silent zero-value fallbacks. Entries 3 and 5 remain
separate source-conversion defects resolved by removing the adapter under
Decision 4; do not fold its compatibility conversions into the shared copier.
Retain separate small traversals where ownership or validation policies differ
enough that sharing would require a configurable reflection framework. Reducing
duplicate code is useful only when it also simplifies the supported behavior.
Sources: [Complexity 4](03-complexity.md#4-clarify-ownership-and-policies-across-the-json-value-walkers),
[Equivalence 2](10-equivalence.md#2-centralize-structural-copying-of-already-normalized-json-values).
## 25. Separate Attempt Accounting From Generation Control Flow
**Maintainability.** Generation coordination interleaves dispatch/retry policy
with parallel return values and repeated evidence/observation projection.
Introduce a small attempt result and focused accounting helpers. Preserve
built-in versus injected-client differences, permit release before callbacks
or backoff, frozen requests, existing retry classification, private evidence,
and known/unknown usage distinctions. Do not collapse legitimately different
dispatch strategies merely to reduce lines.
Sources: [Complexity 5](03-complexity.md#5-extract-attempt-accounting-from-generation-control-flow).
## 26. Move OpenRouter Authentication Protocol Details Into Its Adapter
**Architectural ownership.** Use-case code currently interprets OpenRouter's
account-response fields and provider-relative endpoint while the outbound
adapter owns HTTP execution. Place protocol construction/recognition with the
outbound integration; keep diagnostic selection, applicability, cancellation,
completion, and neutral reporting in the use case. Preserve credential/body
privacy and anonymous probing. No plugin framework, reverse dependency, or
blanket prohibition on HTTP facts is needed. Coordinate the body-bound fix
in entry 2, which is a distinct behavioral change.
Sources: [Boundaries 2](11-boundaries.md#2-put-openrouter-authentication-protocol-details-behind-the-outbound-adapter).
## 27. Narrow Smoke-Value Copy Helpers To Real Consumers
**Ownership cleanup.** A request cloner has only its self-test as a caller;
the full-report cloner is used to detach only a target. Express that actual
copy operation directly and retire unused broader cloning after checking
callers. Keep facade request/report projection, active backend cloning,
provider-map errors, ownership tests, and redaction. Do not introduce shared
public/internal DTOs or an additional full-report copy.
Sources: [Boundaries 3](11-boundaries.md#3-narrow-smoke-value-copy-helpers-to-their-actual-ownership-boundaries).
## 28. Give Bundled Catalog Expectations One Test Owner
**Test duplication.** Complete bundled profile/model/provider expectations are
repeated across several test layers. Keep one independently specified asset
oracle, with smaller tests for distinct loading, wire, and diagnostic behavior.
Use controlled fixtures where bundled churn is irrelevant and structural
assertions rather than formatted-map strings. Retain meaningful bundled
coverage instead of deriving every expected value from the loader under test.
Sources: [Testing 7](08-testing.md#7-bundled-catalog-expectations-have-multiple-test-owners).
## 29. Stop Pinning The Opaque Artifact Hash Algorithm In Tests
**Over-specified tests.** Artifact tests and a benchmark assert a literal hash
algorithm despite the public value being opaque. Assert the documented
equality/ownership relationships and actual byte/size behavior instead; keep
benchmark setup outside its timed work. Coordinate with entry 31, but do not
turn today's hash representation into a new compatibility guarantee.
Sources: [Testing 6](08-testing.md#6-artifact-tests-and-benchmarks-pin-an-explicitly-opaque-hash-algorithm).
## 30. Remove Unconsumed Backend Presence Bookkeeping
**Low-priority state cleanup.** Backend field-state maps and
`QueueCapacitySet` have no runtime reader; effective values and ConfigKit
already own queue defaulting and provenance. Remove only these unused records
and adjust tests to assert effective behavior or operator inspection. Keep
profile/input presence tracking, explicit zero capacity, and derived defaults.
Sources: [Dead code 1](12-deadcode.md#1-remove-backend-presence-bookkeeping-with-no-runtime-consumer).
## 31. Retire Duplicate Fields In Captured Prompt Definitions
**Low-priority representation cleanup.** Captured definitions duplicate the
output format and carry an unused runtime message-file field after content
materialization. Use the captured output contract and text as their respective
sources of truth. Preserve real YAML `content_file` loading, origins, and the
request-override default rule. Removing serialized internal fields changes
current definition hashes: retain documented opaque equality relationships,
not an invented bit-identical encoding promise. Record the observable hash
change in release notes so consumers can account for invalidated comparisons
or caches, without establishing a permanent hash algorithm or encoding contract.
Sources: [Dead code 2](12-deadcode.md#2-retire-legacy-fields-in-the-captured-prompt-representation).
## 32. Remove Unused Private Diagnostic State And Helper Results
**Low-priority cleanup.** A private reachability outcome echoes an endpoint
that report assembly never reads; the schema-file helper returns a directory
that its only caller discards. Remove the unused state/result while preserving
actual sanitized request/report evidence, directory calculation, file checks,
and public single-file schema support. Keep privacy tests against the values
that real execution consumes.
Sources: [Dead code 3](12-deadcode.md#3-remove-unused-diagnostic-state-and-a-discarded-helper-result).
## 33. Remove Orphan Internal Helpers And Their Self-Tests
**Low-priority cleanup.** `filecatalog.RelativePath` and
`resourceNamespaceFromID` have only their own tests as callers, and the runner
test's `stringPtr` helper is entirely unused. Remove those narrow surfaces
without replacement, preserving real discovery, identity qualification, and
namespace inventory/filtering coverage. Reachability from examples alone is
not a reason to remove optional public APIs.
Sources: [Dead code 4](12-deadcode.md#4-remove-orphan-helpers-whose-only-callers-are-their-own-tests).
## 34. Decide Whether To Retain The Legacy Capacity Client Wrapper
**Accepted architectural cleanup; implementation pending.** The old capacity
client wrapper is used only by tests; production dispatch uses the generation
coordinator. [Decision 6](#decision-6-retention-of-the-legacy-capacity-client-wrapper)
selects removal of the production wrapper and its retention documentation.
Migrate the runner scheduling test to the production coordinator and preserve
useful FIFO, cancellation, independent-pool, and panic-release coverage with
the owning components. Keep any useful one-shot scaffolding test-only. This
is not a second scheduling algorithm or a confirmed concurrency defect.
Sources: [Boundaries 1](11-boundaries.md#1-retire-the-test-only-capacity-client-as-a-production-scheduling-surface),
[Dead-code retention qualification](12-deadcode.md#intentional-retention-and-related-findings).
## Resolved Decisions
### Decision 1: ArtifactReader Result Ownership And Lifetime
**Related finding:** [4](#4-resolve-the-artifactreader-buffer-ownership-contract).
**Status:** Accepted; implementation pending.
**Decision:** A successful `Read` transfers the returned artifact and its mutable
body storage to PromptKit. The reader must stop mutating the returned artifact
and body, including through retained aliases. Fresh independent results are the
simplest implementation. A reader may reuse private working buffers if it copies
into independent result storage before returning.
Keep the existing interface signature and defensive adapter copy initially.
Removing redundant copies is a separate optimization, not part of this contract
correction. No borrowing lifetime or acknowledgement/release API is introduced.
**Rationale:** The reader controls storage until return and can therefore make
that handoff safe. Copying only after return cannot make the current permission
to immediately reuse storage safe; a reader-local mutex also cannot protect the
caller's later copy.
**Alternatives considered:** Borrowing until the enclosing operation returns
makes the lifetime difficult for a reader to observe and requires coordination
across concurrent calls. An explicit release protocol enables pooling but adds
lifecycle machinery. Caller-provided buffers or streaming would require a
broader interface redesign. None is needed for this correction.
**Remediation follow-through:** Update GoDoc, adapter assumptions, and concurrency
regressions together. Explain the migration for readers that reuse returned
storage in release notes as a deliberate pre-1.0 contract correction. This
record does not itself implement the change.
### Decision 2: Provider Submission Of Multi-Resource Schemas
**Related findings:** [6](#6-make-provider-native-schema-constraints-self-contained)
and [21](#21-share-schema-compilation-and-declare-the-runners-real-dependency).
**Status:** Accepted; implementation pending.
**Decision:** Require self-contained schema documents. Continue loading the
selected schema from a file and supporting references within that document,
such as `#/$defs/address`. Reject references requiring another document during
preparation with an actionable error. Remove external-resource loading support
and update the owning documentation and tests as a deliberate compatibility
change. Do not introduce a local-only validation mode or implement bundling in
this remediation.
**Rationale:** OpenRouter's documented structured-output request accepts one
schema object, with no accompanying collection of external schema files.
PromptKit currently supports local validation of resources it cannot faithfully
submit. Requiring a self-contained document resolves that mismatch without
adding a schema transformation subsystem. Provider-specific schema restrictions
still apply; self-containment does not guarantee universal provider acceptance.
**Alternatives considered:** Bundling could preserve multi-file authoring and
reuse, but its value does not currently justify the machinery needed to preserve
reference semantics. Retain a [schema bundler](../future.md#schema-bundling) as a
possible future enhancement, not approved implementation work. An explicit
local-only mode would preserve external local validation but add a distinct
execution behavior that is not needed for the selected scope.
**Remediation follow-through:** Cover external-reference rejection and retained
in-document references, including recursion where otherwise supported. Update
schema documentation and release notes, and simplify the shared compilation
work in finding 21 accordingly. This record does not itself implement the change.
### Decision 3: Authentication Response Budget And Overflow Outcome
**Related findings:** [2](#2-bound-authentication-probe-response-consumption)
and [26](#26-move-openrouter-authentication-protocol-details-into-its-adapter).
**Status:** Accepted; implementation pending.
**Decision:** Bound the authentication protocol's response body to 1 MiB
(1,048,576 bytes), defined as a named internal constant. This is a generous
practical processing allowance, not an upstream protocol limit. Do not add a
public configuration option now; keep the value centralized so a future option
can be introduced if needed. This limit does not apply to inference responses
or establish an application deadline.
Enforce the budget against bytes actually read, regardless of declared content
length. Detect overflow, stop reading, and close without unbounded draining.
Report an explicit response-limit diagnostic with credential acceptance unknown,
retaining independently collected HTTP status and timing information. Overflow
is neither evidence of rejected credentials nor proof of malformed JSON. The
consuming application decides what to do with the diagnostic.
**Alternative considered:** A caller-configurable budget with a finite default
would accommodate unusual deployments, but adds public configuration without a
current demonstrated need. Reconsider if such a need arises.
**Remediation follow-through:** Add focused boundary and overflow coverage,
including missing or inaccurate content lengths. Represent overflow explicitly
in the diagnostic report and update its owning documentation. Keep this fix
independent of adapter relocation so architectural cleanup does not delay the
resource remedy. This record does not itself implement the change.
### Decision 4: Exact Numbers And The Source-Conversion Boundary
**Related findings:** [3](#3-avoid-exponential-expansion-during-convenience-source-conversion),
[5](#5-preserve-exact-numbers-in-programmatic-provider-sources), and
[24](#24-centralize-compatible-json-copying-without-conflating-policies).
**Status:** Accepted; implementation pending.
**Decision:** Remove the recursive provider-value compatibility adapter from
`ProfileSource` and `BackendSource`. Supply their provider values directly to
ConfigKit `Mapping`, using its supported input types: nil, built-in strings,
booleans, signed and unsigned integers, finite floats, `map[string]any`, and
`[]any`, recursively. Retain the helpers' ordinary profile/backend field mapping.
ConfigKit owns snapshotting and deferred diagnostics for unsupported values and
cycles. Do not introduce an upstream extension or a PromptKit numeric conversion,
precision-checking, or raw-source validation subsystem for this remediation.
**Consumer impact:** Values formerly accommodated by the adapter, including
`json.Number`, named scalar types, typed maps/slices, arrays, and pointers nested
inside provider values, must be supplied in supported forms. Callers choose any
conversion and handle its errors or acceptable approximation; PromptKit does
not silently make that choice. Ordinary typed profile fields already use
supported forms. This decision does not narrow runtime request overrides.
**Rationale:** The root cause is a mismatch between PromptKit's broader provider
value representation and ConfigKit's mapping inputs. PromptKit's compatibility
adapter introduces both lossy numeric interpretation and pre-handoff graph
expansion. Removing it simplifies the boundary and addresses both defects
without imposing new numeric guarantees on an LLM library.
**Alternatives considered:** Repairing and memoizing the adapter would preserve
more input forms but retain unnecessary conversion machinery. Extending ConfigKit
could move that responsibility upstream but is not needed for the selected scope.
**Remediation follow-through:** Update convenience-source GoDoc, migration/release
notes, and focused tests for direct supported-value handoff, source capture, and
ConfigKit's deferred rejection of unsupported inputs. Remove obsolete adapter
code and tests. Preserve distinct runtime JSON-copying behavior. This is a
deliberate compatibility change; this record does not itself implement it.
### Decision 5: Consumer Go Minimum After The Toolchain Update
**Related finding:** [1](#1-update-the-audited-maintainer-toolchain-for-applicable-security-fixes).
**Status:** Accepted; maintainer-toolchain remediation pending.
**Decision:** Select the maintainer toolchain independently of the consumer Go
minimum. Always use the latest locally available Go version for PromptKit builds
and tests, including ordinary development and release validation. Update the
local installation as needed to address the audit findings; local availability
alone does not establish that those fixes are present.
Normally set the consumer minimum to the initial stable release (`1.x.0`) of
the current selected series. Advance series in minor releases; preserve the
minimum in patch releases. Retain the existing exception for a dependency or
identified correctness requirement that needs a higher patch minimum. This
reaffirms the [release policy](../../policy/release.md#consumer-minimum-and-release-toolchain)
and [release procedure](../../release.md#prepare-the-candidate), extending the
latest-local-toolchain instruction explicitly to ordinary builds and tests.
Advising consumers to update Go for generally applicable vulnerabilities is not
PromptKit's responsibility. Do not add consumer advisories, upgrade notices, or
an ongoing vulnerability-notification obligation for those issues to this
remediation. Downstream toolchain maintenance belongs to the consuming project.
**Alternative considered:** Raising the consumer patch minimum as a routine
response to general Go security advisories would conflate library compatibility
with downstream toolchain maintenance. That approach is not selected.
**Remediation follow-through:** Use the selected local toolchain for the focused
reassessment and clarify ordinary development toolchain selection in contributor
guidance. No new recurring release gate or general consumer security advisory
work is introduced. This record does not itself update the installed toolchain.
### Decision 6: Retention Of The Legacy Capacity Client Wrapper
**Related finding:** [34](#34-decide-whether-to-retain-the-legacy-capacity-client-wrapper).
**Status:** Accepted; implementation pending.
**Decision:** Retire the legacy production capacity client wrapper. Move the
runner's initial-generation and repair scheduling test to the production
generation coordinator. Preserve useful FIFO, cancellation, independent-backend,
and panic-release coverage in tests of the components that own those behaviors.
Keep a small one-shot wrapper as test-only scaffolding if it improves focused
capacity tests; do not retain a production constructor solely for its self-tests.
**Rationale:** All current wrapper callers are tests. Production already uses
the generation coordinator with the same capacity manager. Removal reduces
maintenance surface and makes the runner test reflect actual engine assembly,
without changing the public API or production scheduling behavior.
**Alternative considered:** Retaining the small wrapper as an internal
convenience would avoid test migration, but no current production need justifies
that additional assembly surface.
**Remediation follow-through:** Migrate the useful assertions before removing
the wrapper and update its retention documentation. Keep this cleanup narrowly
scoped; do not redesign the capacity manager or generation coordinator or add
another permit-acquisition layer around the coordinator. This is not a confirmed
concurrency defect or a release blocker. This record does not implement removal.
## Open Decisions
All six decisions above are resolved. Their implementation remains pending;
recording acceptance does not mark the audit findings remediated. No further
open decisions are currently identified in this catalog.