Files
narratio/docs/roadmap/notarius-credential-forwarding.md

260 lines
13 KiB
Markdown

# Typed Notarius Credential Forwarding
Status: Accepted — implementation pending
## Summary
Allow an operator to configure one typed credential reference for the Notarius
stage. Narratio resolves that reference through its existing ConfigKit secrets
bootstrap and supplies the credential to the Notarius subprocess under the
referenced environment-variable name.
The target is a bounded configuration-and-adapter feature that reuses ConfigKit
typed secrets and Narratio's existing subprocess environment and redaction
support. No upstream change or general environment-management framework is
required. This roadmap owns the desired end state and policy; the
[implementation plan](implementation.md) owns execution order and concrete
implementation steps.
## Problem
An enabled Notarius pipeline may select a PromptKit profile that requires an
API key, such as a profile whose `api_key_env` is `OPENROUTER_API_KEY`.
Narratio already supports environment and secrets-directory bootstrap for typed
credentials, but the Notarius configuration section has no credential field.
Consequently, an operator cannot declare the Notarius credential dependency in
Narratio configuration. Supplying the variable to Narratio's environment or
conventional secrets directory is not sufficient under the current public
contract: the Notarius invocation receives Narratio's minimal child
environment, and no selected Notarius credential is forwarded.
This leaves an otherwise valid configured extraction stage unable to
authenticate to a provider without an out-of-band invocation mechanism.
## Required Operator-Facing API
Add one optional typed secret reference at:
```text
pipeline.notarius.llm_api_key
```
Illustrative addition to an otherwise valid pipeline:
```yaml
notarius:
llm_api_key: OPENROUTER_API_KEY
```
`llm_api_key` contains an environment-variable name, never a raw credential.
Its value uses the same typed-secret and ConfigKit bootstrap semantics as other
Narratio credential references:
- when the field is absent, Narratio forwards no Notarius credential and
preserves the current behavior;
- when the field is present, its value must be a valid typed secret reference
that resolves to a nonempty credential during configuration loading;
- an existing process environment value takes precedence over a value loaded
from the selected secrets directory;
- `--secrets-dir` and conventional sibling `secrets/` discovery retain their
existing meanings; and
- a selected profile may replace or explicitly remove the field under ordinary
ConfigKit overlay semantics.
An explicit null has the same credential-delivery meaning as absence. Every
non-null reference surviving the selected profile must resolve, including during
inspection or when extract will not execute. Unselected or removed base
references are not independently resolved. Do not introduce stage-dependent
secret loading or a second environment lookup at execution time.
For a configured reference such as `OPENROUTER_API_KEY`, the Notarius child
process receives the resolved credential under exactly that environment name.
This lets the operator coordinate the Narratio field with the `api_key_env`
selected by the Notarius PromptKit profile without introducing
provider-specific configuration in Narratio.
No new CLI flag is required. The existing Notarius argument vector, pipeline
configuration path, working directory, reference bindings, receipt, and output
contracts remain unchanged.
## Required Architecture and Changes
### Configuration and inspection
Add an optional `*configkit.Secret` to `NotariusConfig`, following the existing
typed credential pattern. ConfigKit owns reference syntax, effective-profile
resolution, and access to the resolved value; the application continues to own
the one-per-invocation secrets-directory bootstrap. The field defaults to absent.
Extend the relevant safe configuration projections, serialization, provenance,
and tests so this field is visible by its public reference name. Review both
effective inspection and generated/persisted configuration paths; protecting
`config show` alone is insufficient. Do not serialize an adapter invocation
request or a raw credential-bearing structure for diagnostics.
### Extract and adapter delivery
Carry the optional credential through extract's existing Notarius invocation
boundary. Keep transport-specific environment construction in the Notarius
adapter and expose the resolved value only at the trusted delivery boundary.
Reuse the subprocess runner's `EnvOverrides` for the selected name/value pair
and `SensitiveEnvNames` to register that same name for redaction. Register custom
names as well as familiar provider names; the built-in sensitive-name list is
not sufficient for this feature.
The child retains Narratio's existing minimal inherited environment plus the
explicit credential override. There is no broad process-environment inheritance,
provider-name remapping, or forwarding of unrelated bootstrapped secrets. An
absent reference adds neither an override nor a credential requirement.
### Ownership
Keep configuration semantics in `internal/config`, bootstrap in `internal/app`,
invocation orchestration in `internal/stage`, and environment/redaction delivery
in `internal/adapters/notarius` and the shared subprocess boundary. Reuse the
existing helpers rather than introducing another secret resolver or redactor.
The [architecture policy](../policy/architecture.md),
[configuration internals](../internal/configuration.md), and
[adapter internals](../internal/adapters.md) remain the canonical owners of the
implemented system's boundaries.
## Inspection and Diagnostic Contract
- `narratio config validate` resolves the configured secret reference and
fails before stage execution when it is missing or empty.
- `narratio config show` may expose the non-secret reference name, such as
`OPENROUTER_API_KEY`, but never the resolved credential value.
- `narratio config sources` and `narratio config diff` retain their existing
secret-safe behavior.
- Configuration digests, manifests, generated configuration, command
arguments, persisted diagnostics, receipts, and other operator-visible
output must not contain the resolved credential value.
- Errors may identify the field or unresolved environment-variable name but
must not include credential bytes.
The selected credential must receive the existing streaming redaction protection
on captured stdout and stderr, including logs, captured receipt output, and
stderr-derived errors on nonzero exit, timeout, or cancellation. Test the delivery
of the dynamically selected sensitive name; do not create a provider-specific
redaction exception or a second log-sanitization mechanism.
### Downstream responsibility boundary
Narratio must not place credential values in its authored configuration,
arguments, manifests, or metadata, and must redact the selected value from
subprocess streams it captures. Notarius remains responsible for keeping
credentials out of files it writes directly, including bundle artifacts and
diagnostics. Captured-stream redaction is not a filesystem sandbox and does not
guarantee sanitization of arbitrary downstream files or transformed/encoded
secret values. This feature does not add recursive scanning or rewriting of
Notarius output bundles. Such rewriting could corrupt valid artifacts and would
not establish a general non-disclosure guarantee.
## Resume and Configuration Identity
Authentication is operational configuration, not extraction content. Neither
the credential value nor its reference name becomes part of extract's semantic
resume fingerprint. Credential rotation, renaming, addition, or removal alone
must not invalidate a successfully recorded extraction or its dependents.
The effective configuration projection may include the public reference name,
so changing that name can appear in `config diff` and change the effective
configuration digest. Rotating only the resolved value must not change that
digest. Preserve the existing distinction between configuration provenance and
stage-owned resume evidence; do not add a blanket digest-based invalidation.
Normal configuration loading still requires any selected reference to resolve
even when the prior extraction can be reused.
## Compatibility
The field is optional and defaults to absent. Existing configurations retain
their current behavior without migration.
The credential name belongs to deployment configuration rather than to a
specific provider. Narratio does not infer a name from a Notarius pipeline,
profile ID, backend, model, or configuration file. Operators must select a name
that agrees with the Notarius PromptKit profile they deploy.
## Acceptance Criteria
- A pipeline with Notarius enabled and no `notarius.llm_api_key` continues to
load and invoke Notarius with no forwarded provider credential.
- A pipeline may set `notarius.llm_api_key` to a valid environment-variable
reference.
- The reference resolves from an existing process environment value or from
Narratio's existing explicit or conventional secrets-directory bootstrap.
- A missing or empty configured credential fails configuration loading before
Notarius execution.
- A successful Notarius invocation receives the resolved value under exactly
the configured reference name.
- Unrelated credentials present in Narratio's environment or secrets directory
are not made available to Notarius merely because this field is configured.
- Base and named-profile configuration follow ordinary ConfigKit replacement,
explicit-null, source-reporting, diff, and secret-resolution semantics.
- Effective inspection exposes at most the safe reference name and never the
resolved value.
- No raw credential appears in Narratio-authored command arguments, generated
configuration, manifests, metadata, or test output. Captured receipt/log streams
and errors redact the selected value within the responsibility boundary above.
- A custom environment-variable name not present in the built-in sensitive-name
list receives the same redaction protection as a known provider name, on both
successful and failing subprocess execution.
- Credential rotation or reference-name changes do not alter extract's semantic
fingerprint or invalidate a reusable extraction. Inspection reflects name
changes without revealing values; value-only rotation leaves the safe digest
unchanged.
- The existing Notarius CLI arguments and result-validation contract remain
unchanged.
- Focused tests use synthetic credentials and a controlled Notarius substitute;
they do not contact a model provider or require a real API key.
- Configuration, CLI, integration, example, troubleshooting, and release
documentation are updated only where their existing canonical ownership
requires it when the feature is implemented.
Use focused behavioral tests at the configuration, extract/adapter delivery,
and captured-output boundaries. Retain shared subprocess tests for its generic
streaming guarantees rather than duplicating their full matrix. Verify the
assembled invocation with a controlled executable and synthetic credentials,
including proof that an unrelated credential is not forwarded. Follow the
[testing policy](../policy/testing.md) and the normal
[development validation](../development.md#validation); no live-provider
authentication is an acceptance gate.
## Target End State
An operator supplies a named API-key file through the existing secrets directory
or sets that environment variable, declares `notarius.llm_api_key`, and configures
the matching `api_key_env` in Notarius's selected PromptKit profile. Narratio
validates the reference, delivers only the selected credential to Notarius, and
keeps its own configuration and diagnostics credential-safe. Existing pipelines
need no migration, and changing authentication does not rerun completed analysis
work. No new CLI, dependency upgrade, or upstream feature is required.
## Non-goals
- Adding an arbitrary environment-variable map to the Notarius stage.
- Forwarding every variable loaded from the secrets directory.
- Inferring provider, backend, profile, model, or credential names from
Notarius configuration.
- Managing secret files, credential values, rotation, encryption, or an
external secret store.
- Changing Notarius configuration syntax, PromptKit profile syntax, CLI flags,
receipt schemas, pipeline definitions, or output bundles.
- Supporting more than one Notarius provider credential in this feature.
- Validating a credential with its provider during configuration loading.
- Adding credentials to command-line arguments, ordinary YAML values, or
generated invocation files.
- Scanning or sanitizing arbitrary files created directly by downstream tools.
- Changing resume semantics, pipeline path bases, artifact schemas, or the
existing minimal inherited subprocess environment.
## Consumer Dependency
The D&D Ansible pipeline requires this operator-facing contract before it can
provide complete suite-managed credential delivery. Its intended deployment
places files named for configured secret references in Narratio's conventional
`secrets/` directory. That deployment can select and provision the value only
after Narratio provides a typed field that forwards the selected Notarius
credential under the same reference name.