Documentation
¶
Overview ¶
Package adapter holds the interoperability seam for specd: the versioned request/result envelopes, result-identity validation, data classification, and the opt-in adapter runner. It is deliberately kept out of the trusted core (internal/core, internal/core/gates, internal/context, and the DAG/ report paths): core generates adapter requests as data and consumes adapter results only after they have been validated and pinned, but core must never import this package. That one-way boundary — enforced by the import guard in this package's tests, not by convention — is what keeps the binary free of runtime dependencies and free of any model, eval-service, deployment, telemetry-backend, protocol, or network code in a gate, DAG, or report path.
The W0 baseline ships only the boundary invariant. Later waves add the envelope types, identity checks, classification, runner, and conformance suite; those additions live here so the guard keeps core clean as they land.
Index ¶
- Constants
- func Historical(res Result, current map[string]string) bool
- func MatchIdentity(req Request, res Result) error
- func MissionFromRequest(req Request) (orchestration.MissionV1, error)
- func RedactForExport(refs []Ref, p ExportPolicy) (kept []Ref, redactions []Redaction)
- func ValidateFeedbackCommit(root string, f ReleaseFeedbackV1) error
- type Adapter
- type Class
- type ErrorClass
- type ExitClass
- type ExportPolicy
- type Finding
- type Limits
- type Measurements
- type OTelSpan
- type Redaction
- type Ref
- type ReleaseFeedbackV1
- type Request
- type Result
- type Status
- type Subject
Constants ¶
const FeedbackSchemaV1 = "release_feedback/v1"
FeedbackSchemaV1 versions runtime-feedback payload semantics independently from adapter, CLI, and on-disk state schemas.
const MaxInlineBytes = 64 * 1024
MaxInlineBytes bounds opt-in inline content on a reference (R4.3). By default references carry only a digest; inline bytes are opt-in and size-bounded.
const SchemaVersion = "adapter/v1"
SchemaVersion is the single frozen version of the common adapter envelope. The common core is co-designed from Domains 04/05/07/08 P0 field demands and frozen once here; payload-specific fields are additive extensions carried in Payload and owned by the consuming domain (design.md "Common envelope fields").
Variables ¶
This section is empty.
Functions ¶
func Historical ¶
Historical reports whether a result is stale relative to the current pinned subject (R3.3): if any input digest it was computed against differs from the digest of the current subject, the result describes past state and must be marked historical rather than mistaken for current.
func MatchIdentity ¶
MatchIdentity rejects a result whose identity does not match its pinned request (R3.1/R3.2). It must be called before a result's status is allowed to satisfy any gate, completion, deploy, or eval decision: a status of "succeeded" is meaningless if the result does not belong to the request that asked for it. Every mismatch returns a stable ErrIdentityMismatch finding.
func MissionFromRequest ¶
func MissionFromRequest(req Request) (orchestration.MissionV1, error)
MissionFromRequest performs strict payload decoding and verifies duplicated common-envelope identity/authority pins before returning mission semantics.
func RedactForExport ¶
func RedactForExport(refs []Ref, p ExportPolicy) (kept []Ref, redactions []Redaction)
RedactForExport strips inline content that policy does not permit to cross a boundary, returning the sanitized references and a record of every removal (R4.2/R4.3). References and digests are always preserved; only inline bytes are removed, so the result still identifies its inputs by content address.
func ValidateFeedbackCommit ¶
func ValidateFeedbackCommit(root string, f ReleaseFeedbackV1) error
ValidateFeedbackCommit resolves untrusted feedback identity at import boundary.
Types ¶
type Adapter ¶
type Adapter struct {
Name string `json:"name"`
Version string `json:"version,omitempty"`
SchemaVersion string `json:"schema_version,omitempty"` // adapter-envelope schema the executable speaks
Path string `json:"path"` // executable resolved by the project
Args []string `json:"args,omitempty"`
Capabilities []string `json:"capabilities,omitempty"` // capabilities_offered by this adapter
EnvAllow []string `json:"env_allow,omitempty"` // env var NAMES the adapter process may see
Enabled bool `json:"enabled"` // false ⇒ configured but disabled
}
Adapter is the manifest of one opt-in, project-selected integration executable. It is data only: the runner drives it over stdin/stdout JSON and never links it into the process (the boundary invariant). The same manifest backs read-only `specd adapters` inspection, so it carries names, paths, versions, and offered capabilities — never secret values (R6.3).
type Class ¶
type Class string
Class is a data-classification label from the fixed taxonomy (R4.1). Every adapter reference carries a class so the boundary layer can decide what may cross a process/network/A2A/CI/telemetry boundary and what must be redacted.
const ( ClassPublicMetadata Class = "public-metadata" ClassSpecText Class = "spec-text" ClassSourcePath Class = "source-path" ClassSourceContent Class = "source-content" ClassPrompt Class = "prompt" ClassToolOutput Class = "tool-output" ClassSecret Class = "secret" ClassTelemetry Class = "telemetry" ClassProductionFeedback Class = "production-feedback" )
func AllClasses ¶
func AllClasses() []Class
AllClasses returns the taxonomy in a stable order. The count is asserted in tests so a class cannot be added or dropped without a deliberate change.
func (Class) Restricted ¶
Restricted reports whether c names content that must not cross a boundary in the clear by default (R4.2): secrets, raw source content, and prompts. These are absent or redacted unless a project policy explicitly opts them in.
type ErrorClass ¶
type ErrorClass string
ErrorClass is a stable classification for a rejected envelope (R2.2).
const ( ErrMalformed ErrorClass = "malformed" ErrUnknownVersion ErrorClass = "unknown_schema_version" ErrUnknownKind ErrorClass = "unknown_kind" ErrUnknownField ErrorClass = "unknown_field" ErrInvalidValue ErrorClass = "invalid_field_value" ErrIdentityMismatch ErrorClass = "identity_mismatch" )
type ExitClass ¶
type ExitClass string
ExitClass distinguishes the ways a runner invocation can end (R2.4/R6.2).
type ExportPolicy ¶
type ExportPolicy struct {
AllowInline []Class
}
ExportPolicy governs which inline content may cross a boundary. The zero value is the safe default: only public-metadata inline is exported; every other class is reference+digest only. AllowInline opts specific classes in.
type Finding ¶
type Finding struct {
Class ErrorClass `json:"class"`
Field string `json:"field,omitempty"`
Message string `json:"message"`
}
Finding is a typed, stable error explaining why an envelope failed closed.
func NegotiateCapabilities ¶
NegotiateCapabilities reports whether an adapter offering `offered` can satisfy a request requiring `required` (R7.1). Acceptance must occur before any side effect, so Run negotiates before invoking the executable. A missing capability returns a stable finding naming it; nil means every requirement is met.
type Limits ¶
type Limits struct {
TimeoutMS int64 `json:"timeout_ms,omitempty"`
OutputBytes int64 `json:"output_bytes,omitempty"`
}
Limits bounds an adapter invocation deterministically.
type Measurements ¶
Measurements are named numeric results (scores, tokens, durations). Map keys are emitted in sorted order by encoding/json, keeping output byte-stable.
type OTelSpan ¶
type OTelSpan struct {
TraceID string `json:"trace_id"`
SpanID string `json:"span_id"`
Name string `json:"name"`
Timestamp string `json:"timestamp"`
Attributes map[string]string `json:"attributes,omitempty"`
}
OTelSpan is a dependency-free OpenTelemetry-compatible span projection. Attributes contain bounded classifications and correlation only: never raw source paths, source content, prompts, tool output, or secrets.
func ExportNeutralEvents ¶
ExportNeutralEvents maps Domain 07's canonical local schema to an OpenTelemetry-compatible projection. It performs no I/O; transport remains an external adapter concern. Correlation and privacy audit fields survive as bounded attributes, while raw content cannot enter because EventV1 has no such field.
func ExportOTel ¶
func ExportOTel(events []orchestration.ObservableEvent) ([]OTelSpan, error)
ExportOTel validates local observable events then projects safe span data.
type Redaction ¶
type Redaction struct {
Ref string `json:"ref"`
Class Class `json:"class"`
Reason string `json:"reason"`
}
Redaction records that a reference's inline content was removed at a boundary so an audit can see a transfer policy applied rather than a silent drop.
type Ref ¶
type Ref struct {
Name string `json:"name"`
Digest string `json:"digest"`
Class Class `json:"class"`
Inline string `json:"inline,omitempty"`
}
Ref is a content reference: a named digest with a data class, and optional size-bounded inline content (R4.3).
type ReleaseFeedbackV1 ¶
type ReleaseFeedbackV1 struct {
SchemaVersion string `json:"schema_version"`
SourceSpec string `json:"source_spec"`
SuccessorSpec string `json:"successor_spec"`
ReleaseID string `json:"release_id"`
Environment string `json:"environment"`
GitHead string `json:"git_head"`
ObservedAt string `json:"observed_at"`
EvidenceRefs []string `json:"evidence_refs"`
}
ReleaseFeedbackV1 is bounded, untrusted runtime data. It can identify and link successor maintenance work; it carries no command or mutation field.
func FeedbackFromRequest ¶
func FeedbackFromRequest(req Request) (ReleaseFeedbackV1, error)
FeedbackFromRequest decodes strictly and verifies duplicated release pins. Returned value remains data; core owns whether a maintenance edge is valid.
type Request ¶
type Request struct {
SchemaVersion string `json:"schema_version"`
Kind string `json:"kind"`
RequestID string `json:"request_id"`
CorrelationID string `json:"correlation_id"`
Subject Subject `json:"subject"`
Actor string `json:"actor,omitempty"`
AuthorityRef string `json:"authority_ref,omitempty"`
InputRefs []Ref `json:"input_refs,omitempty"`
CapabilitiesRequired []string `json:"capabilities_required,omitempty"`
Limits Limits `json:"limits"`
StartedAt string `json:"started_at"`
AdapterName string `json:"adapter_name"`
Payload json.RawMessage `json:"payload,omitempty"`
}
Request is the versioned envelope core generates for an adapter (R2.1).
func DecodeRequest ¶
DecodeRequest parses and validates a request envelope, failing closed with a typed Finding on any unknown version/kind/field or malformed input (R2.2).
func FeedbackRequest ¶
func FeedbackRequest(f ReleaseFeedbackV1, requestID, correlationID, adapterName string) (Request, error)
FeedbackRequest wraps runtime feedback in the common boundary envelope.
func MissionRequest ¶
func MissionRequest(m orchestration.MissionV1, requestID, correlationID, adapterName string) (Request, error)
MissionRequest maps specd's canonical mission onto the common adapter envelope. Mission payload remains domain-owned while identity and authority are duplicated in the common pins so generic adapters can reject mismatch.
type Result ¶
type Result struct {
SchemaVersion string `json:"schema_version"`
Kind string `json:"kind"`
RequestID string `json:"request_id"`
CorrelationID string `json:"correlation_id"`
Subject Subject `json:"subject"`
AdapterName string `json:"adapter_name"`
AdapterVersion string `json:"adapter_version"`
CapabilitiesOffered []string `json:"capabilities_offered,omitempty"`
Status Status `json:"status"`
ExitClass ExitClass `json:"exit_class"`
Retryable bool `json:"retryable"`
OutputRefs []Ref `json:"output_refs,omitempty"`
EvidenceRefs []Ref `json:"evidence_refs,omitempty"`
Measurements Measurements `json:"measurements,omitempty"`
Redactions []Redaction `json:"redactions,omitempty"`
InputDigests map[string]string `json:"input_digests,omitempty"`
StartedAt string `json:"started_at"`
FinishedAt string `json:"finished_at"`
Payload json.RawMessage `json:"payload,omitempty"`
}
Result is the versioned envelope an adapter returns (R2.1).
func DecodeResult ¶
DecodeResult parses and validates a result envelope, failing closed with a typed Finding on any unknown version/kind/field or malformed input (R2.2).
func DecodeResultValue ¶
DecodeResultValue validates an already-constructed result value, so callers building a result in-process share the same fail-closed schema check.
func Run ¶
Run invokes adapter a for req, feeding the canonical request JSON on stdin and decoding the result envelope from stdout, bounded by req.Limits and a.EnvAllow.
It fails closed on every path (R6.1/R6.2): a missing binary, timeout, oversized output, malformed result, or non-zero exit each yields a typed failing Result pinned to the request — none is recorded as success and none falls back to unsafe local execution. Capability negotiation (R7.1) and identity validation (R3) run around the invocation so an adapter result can never satisfy a gate before it is proven to belong to the request.
Secrets reach the adapter only through the allowlisted execution environment (R6.3): Run passes exactly the env entries whose NAME is in a.EnvAllow and reads nothing from .specd artifacts or model context. The non-nil (possibly empty) env means the child never inherits the parent's environment.
The returned error, when non-nil, is the *Finding explaining the failing or rejected record; callers record the Result as blocked/failed evidence.
type Status ¶
type Status string
Status is the stable result class (R2.4).
type Subject ¶
type Subject struct {
SpecSlug string `json:"spec_slug,omitempty"`
TaskID string `json:"task_id,omitempty"`
MissionID string `json:"mission_id,omitempty"`
GitHead string `json:"git_head,omitempty"`
ReleaseID string `json:"release_id,omitempty"`
Environment string `json:"environment,omitempty"`
}
Subject is the pinned work identity shared by a request and its result.