Documentation
¶
Overview ¶
Package core is L1 of the SigComply CLI: the frozen Go interfaces and structs that every higher layer depends on. Framework, Policy, EvidenceRecord, Envelope, Vault, Rule, SourcePlugin, CloudClient, SubmissionPayload, and their supporting value types live here.
Once published these types are stable. The aggregation boundary (SubmissionPayload) is structurally counts-only and must not gain fields that could carry resource identifiers across L6.
See docs/architecture/02-layers.md for the full layer contract.
Index ¶
- Constants
- func PolicyCadences(p *Policy) []string
- func PolicyContentHash(p *Policy, schemaDigests map[string]string) string
- type AggregatedPolicy
- type AppliedException
- type CIEnvironment
- type CarryForwardRef
- type CloudClient
- type Control
- type Envelope
- type EnvelopeSignature
- type EvidenceRecord
- type EvidenceType
- type Framework
- type FrameworkRunSummary
- type Manifest
- type ManifestSignature
- type ParameterSpec
- type PeriodAggregate
- type Policy
- type PolicyRef
- type PolicyResult
- type PolicyState
- type PolicyStatus
- type Repository
- type Rule
- type RuleInput
- type RuleResult
- type RunSummary
- type Severity
- type Slot
- type SlotCardinality
- type SlotRequest
- type SourcePlugin
- type SubmissionPayload
- type Vault
- type Violation
Constants ¶
const CadenceOnPush = "on_push"
CadenceOnPush is the virtual cadence value representing the on_push axis. A policy's effective cadences are its declared Cadence value plus this constant if its OnPush field is true. The planner treats "fires on every push" and "fires on a schedule" as members of the same set, so a single set-intersection filter (Filter.Cadences) handles both axes uniformly.
const PolicyStateSchemaVersion = "policy-state.v1"
PolicyStateSchemaVersion is the schema stamp on the per-policy state shard. Bumped on any wire-format change.
const RunSummarySchemaVersion = "summary.v1"
RunSummarySchemaVersion is stamped on every vault-side framework run summary. Bumped on any wire-format change.
Variables ¶
This section is empty.
Functions ¶
func PolicyCadences ¶ added in v0.21.0
PolicyCadences returns the policy's effective cadence set: its declared Cadence value plus CadenceOnPush if OnPush is true. Used by the planner for set-intersection filtering against Filter.Cadences and by orchestrator.DueCadences for scheduled-mode dispatch. Returns at most two entries.
func PolicyContentHash ¶ added in v0.21.0
PolicyContentHash computes the SHA-256 of a canonicalized policy spec plus its referenced evidence-type schema digests. A change to the policy YAML (rule reference, severity, slot accepts list, parameters) or any referenced schema produces a different hash; the planner treats hash mismatch with PolicyState.LastPolicyHash as "due regardless of cadence" so a bundle update can never silently re-certify old evidence with new rules.
schemaDigests is a map keyed by evidence-type ID; values are the digests of the corresponding JSON Schema as registered. An empty map is acceptable (callers without schema-digest access pass nil) — the hash will still discriminate policy-spec changes, just not schema bumps.
Types ¶
type AggregatedPolicy ¶
type AggregatedPolicy struct {
PolicyID string `json:"policy_id"`
ControlID string `json:"control_id"`
Status PolicyStatus `json:"status"`
Severity Severity `json:"severity"`
Category string `json:"category,omitempty"`
ResourcesEvaluated int `json:"resources_evaluated"`
ResourcesFailed int `json:"resources_failed"`
Message string `json:"message"`
RuleVersion string `json:"rule_version,omitempty"`
// ConfiguredCadence is the cadence string in effect at this run
// (e.g., "daily", "every:6h"). Non-identifying.
ConfiguredCadence string `json:"configured_cadence,omitempty"`
// LastEvaluatedAt is the start time of the most recent run that
// actually evaluated this policy. For freshly-evaluated rows it
// equals StartedAt; for carry-forward rows it points to the
// earlier run. Non-identifying.
LastEvaluatedAt time.Time `json:"last_evaluated_at,omitempty"`
// NextDueAt is the wall-clock time after which the policy is due
// to be re-evaluated. Zero when the policy is always due (cadence
// "continuous" / "every:0s") or when the most recent terminal
// status was not pass (on_fail_retry → due on next run).
NextDueAt time.Time `json:"next_due_at,omitempty"`
// IsCarriedForward is true when this row references a prior
// evaluation rather than a fresh one in this run.
IsCarriedForward bool `json:"is_carried_forward,omitempty"`
// PolicyContentHash is the SHA-256 hash of the policy spec +
// referenced evidence-type schemas at this run. The cloud uses
// it to detect a bundle bump that may invalidate prior
// evaluations.
PolicyContentHash string `json:"policy_content_hash,omitempty"`
}
AggregatedPolicy is the per-policy projection that crosses the boundary. Counts only — no violation lists, no resource IDs. The Message string is regenerated from counts by the aggregator, never copied from the rule's violation text.
Cadence-related fields (ConfiguredCadence, LastEvaluatedAt, NextDueAt, IsCarriedForward, PolicyContentHash) are non-identifying scalars: they describe schedule/staleness, not who or what. The dashboard uses them to render staleness badges and "next due in N" without recomputing locally. The reflection test in cloud_test.go ensures no identity-carrying field can be added accidentally.
type AppliedException ¶ added in v0.20.0
type AppliedException struct {
PolicyID string `json:"policy_id"`
State string `json:"state"`
Reason string `json:"reason,omitempty"`
ApprovedBy string `json:"approved_by,omitempty"`
ApprovedAt string `json:"approved_at,omitempty"`
ExpiresAt string `json:"expires_at,omitempty"`
ResourceID string `json:"resource_id,omitempty"`
ResourcePattern string `json:"resource_pattern,omitempty"`
}
AppliedException is the snapshot of a planner-resolved exception that was in effect for the run. The shape mirrors spec.ExceptionConfig in .sigcomply.yaml, plus the resolved state and policy ID so an auditor reading the manifest doesn't need the project config to reconstruct who waived what and why.
type CIEnvironment ¶
type CIEnvironment struct {
Provider string `json:"provider"`
Workflow string `json:"workflow,omitempty"`
RunURL string `json:"run_url,omitempty"`
WorkerImage string `json:"worker_image,omitempty"`
}
CIEnvironment captures CI-runner metadata. Workflow names and run URLs are CI-system artifacts, not customer evidence.
type CarryForwardRef ¶ added in v0.21.0
type CarryForwardRef struct {
LastEvaluatedAt time.Time
LastEvaluatedRun string
LastEnvelopeRef string
LastKnownStatus PolicyStatus
SkipReason string
}
CarryForwardRef pins a carry-forward result to a specific prior evaluation. The pair (LastEvaluatedRun, LastEnvelopeRef) is the vault path to a signed envelope an auditor can re-verify independently; LastKnownStatus is the status that prior evaluation produced. SkipReason is the planner's human-readable explanation for why this run did not re-evaluate.
type CloudClient ¶
type CloudClient interface {
Submit(ctx context.Context, payload SubmissionPayload) error
}
CloudClient transmits SubmissionPayload to a configured dashboard endpoint (SigComply Cloud or a self-hosted backend). It is the only consumer of SubmissionPayload outside the aggregator.
type Control ¶
type Control struct {
ID string
Name string
Description string
Category string
BaselineSeverity Severity
}
Control is one item in a framework's control catalog.
type Envelope ¶
type Envelope struct {
FormatVersion string `json:"format_version"`
ProducedAt time.Time `json:"produced_at"`
Records []EvidenceRecord `json:"records"`
Signature EnvelopeSignature `json:"signature"`
}
Envelope is the signed wrapper around a batch of EvidenceRecords. Every envelope is independently verifiable: the public key and signature live inside the envelope, so an auditor with one envelope file and nothing else can verify it offline.
type EnvelopeSignature ¶
type EnvelopeSignature struct {
Algorithm string `json:"algorithm"`
PublicKey []byte `json:"public_key"`
Value []byte `json:"value"`
}
EnvelopeSignature is the Ed25519 signature over canonical JSON of {format_version, produced_at, records}. The keypair is ephemeral — generated per envelope at write time and discarded the instant the signature is computed.
type EvidenceRecord ¶
type EvidenceRecord struct {
Type string `json:"type"`
ID string `json:"id"`
IdentityKey string `json:"identity_key,omitempty"`
Payload json.RawMessage `json:"payload"`
SourceID string `json:"source_id"`
CollectedAt time.Time `json:"collected_at"`
}
EvidenceRecord is one observation produced by a source plugin. IdentityKey is set only when the evidence type has a meaningful cross-source identity (e.g. an email for user_record across aws.iam and okta); leaving it empty disables cross-source dedup.
type EvidenceType ¶
type EvidenceType struct {
ID string `json:"id"`
Version int `json:"version"`
Schema json.RawMessage `json:"schema"`
}
EvidenceType is a versioned evidence-shape schema. The Schema is a JSON Schema document; collected records are validated against it before being wrapped in an Envelope.
type Framework ¶
type Framework interface {
ID() string
Version() string
Controls() []Control
Policies() []PolicyRef
}
Framework is a shipped or extension compliance framework — the catalog of controls plus the set of policies that contribute to each control.
type FrameworkRunSummary ¶ added in v0.21.0
type FrameworkRunSummary struct {
SchemaVersion string `json:"schema_version"`
RunID string `json:"run_id"`
Framework string `json:"framework"`
PeriodID string `json:"period_id"`
CompletedAt time.Time `json:"completed_at"`
Policies []PolicyResult `json:"policies"`
}
FrameworkRunSummary is the per-run, framework-level summary persisted at {framework}/{periodID}/run_*/summary.json. This shape is vault-side and may carry full-fidelity per-policy references; the privacy-bounded SubmissionPayload is built independently by the aggregator from the same []PolicyResult.
Auditors read this file for the run; the framework's separate period summary (one per (framework, periodID), rebuilt every run inside that period) aggregates these into the period view.
type Manifest ¶
type Manifest struct {
SchemaVersion string `json:"schema_version"`
RunID string `json:"run_id"`
Framework string `json:"framework,omitempty"`
PeriodID string `json:"period_id,omitempty"`
StartedAt time.Time `json:"started_at"`
CompletedAt time.Time `json:"completed_at"`
FileHashes map[string]string `json:"file_hashes"`
ExceptionsApplied []AppliedException `json:"exceptions_applied,omitempty"`
Signature ManifestSignature `json:"signature"`
}
Manifest is the per-run signed integrity root. A single Ed25519 signature over FileHashes binds every file in the run folder; any later modification to a hashed file invalidates the manifest.
M5 shipped the minimal shape sufficient to sign and round-trip; later milestones layer optional fields on top (framework + period for reporting/integrity, exceptions_applied for the exception register view). See docs/architecture/05-vault-layout.md §Per-run manifest.
type ManifestSignature ¶
type ManifestSignature struct {
Algorithm string `json:"algorithm"`
PublicKey []byte `json:"public_key"`
Value []byte `json:"value"`
}
ManifestSignature mirrors EnvelopeSignature: a fresh ephemeral Ed25519 keypair is generated at signing time, the private key is zeroed immediately, and the public key is embedded so the manifest is independently verifiable.
type ParameterSpec ¶
type ParameterSpec struct {
Type string
Default any
Min any
Max any
Enum []any
Pattern string
Description string
}
ParameterSpec describes a tunable per-project value on a policy. Default/Min/Max/Enum are typed `any` because the value's static type is named by the Type field (bool, int, string, duration, …).
type PeriodAggregate ¶ added in v0.21.0
type PeriodAggregate struct {
EvaluationsInPeriod int `json:"evaluations_in_period"`
PassCount int `json:"pass_count"`
FailCount int `json:"fail_count"`
LongestFailureStreak time.Duration `json:"longest_failure_streak,omitempty"`
FirstEvaluationAt time.Time `json:"first_evaluation_at,omitempty"`
LastEvaluationAt time.Time `json:"last_evaluation_at,omitempty"`
LongestGapBetweenEvaluations time.Duration `json:"longest_gap_between_evaluations,omitempty"`
}
PeriodAggregate is the per-policy timeline summary for sub-period cadences. When a policy's cadence is shorter than the audit period (e.g., daily MFA check inside a quarterly period), the summary's "latest status" alone does not answer the auditor's real question — "did this control hold continuously throughout the period?"
PeriodAggregate, when present on a policy result, answers it: number of evaluations, pass/fail breakdown, longest failure streak, longest gap between evaluations. Absent for period-aligned cadences (quarterly inside a quarterly period — there is only one data point).
NOTE: PeriodAggregate is populated by `sigcomply audit-ledger` which scans the run-folder history for the period. The single-run path does not compute it (a single run cannot know its own period history without scanning the vault). Reserved as a typed field on PolicyResult so the audit-ledger command can populate it without schema-bumping later.
type Policy ¶
type Policy struct {
ID string
Control string
Description string
Remediation string
Severity Severity
Category string
Cadence string
OnPush bool
Slots map[string]Slot
Parameters map[string]ParameterSpec
RuleRef string
Tags []string
}
Policy is the fully-resolved spec used by the planner and evaluator. Specs are loaded from policy.yaml files at L0; this is the in-memory shape with the rule reference still as a string ID — the registry resolves it to a Rule implementation at plan time.
type PolicyRef ¶
type PolicyRef struct {
PolicyID string
}
PolicyRef points from a framework to a registered policy by ID. The PolicyRegistry resolves the ID to the full Policy spec.
type PolicyResult ¶
type PolicyResult struct {
PolicyID string
ControlID string
Status PolicyStatus
Severity Severity
Category string
EffectiveParams map[string]any
Violations []Violation
ResourcesEvaluated int
ResourcesFailed int
EvidenceEnvelopes []string
RuleVersion string
Diag map[string]any
// ConfiguredCadence is the cadence string in effect at this run
// (e.g., "daily" or "every:6h"). Captured on every result so the
// framework summary and the audit ledger can show the cadence
// without recomputing it. Same value as in PolicyState.
ConfiguredCadence string
// PolicyContentHash is the SHA-256 of the canonicalized policy
// spec plus referenced evidence-type schemas at this run.
// Auditors comparing two runs can detect a policy/schema update
// by comparing this field.
PolicyContentHash string
// NextDueAt is the wall-clock time after which the policy is due
// to be re-evaluated under its configured cadence. Zero for
// "continuous" / "every:0s" cadences (always due) and for
// policies whose most recent terminal status was not pass (in
// which case the on_fail_retry rule applies on the next run).
NextDueAt time.Time
// CarryForward is non-nil iff Status is StatusCarriedForward. It
// references the prior evaluation that this run inherits from.
// The reference is hash-tied to the original signed envelope so
// an auditor can verify it offline without trusting the CLI.
CarryForward *CarryForwardRef
// PeriodAggregate, when non-nil, summarizes every evaluation of
// this policy across the current audit period. Populated by
// `sigcomply audit-ledger`, not by the single-run path — a
// single run cannot know its period history without scanning
// the vault. See PeriodAggregate's doc for the rationale.
PeriodAggregate *PeriodAggregate
}
PolicyResult is the per-policy outcome with full fidelity — includes violation details and resource IDs. This shape is what L7 (vault) persists. L6 (aggregator) projects it into the privacy-bounded AggregatedPolicy before any cloud submission.
PolicyResult is vault-side; nothing in this struct crosses the aggregation boundary directly.
type PolicyState ¶ added in v0.21.0
type PolicyState struct {
SchemaVersion string `json:"schema_version"`
PolicyID string `json:"policy_id"`
Framework string `json:"framework"`
// LastRunAt is the run-start timestamp of the most recent run that
// evaluated this policy (pass, fail, error, or skipped-with-fresh-
// data). Carried-forward runs do NOT update LastRunAt — by
// definition they did not evaluate.
LastRunAt time.Time `json:"last_run_at"`
// LastPassAt is the run-start timestamp of the most recent run that
// evaluated this policy and produced StatusPass. Cadence gating
// uses this field, not LastRunAt — so a failed policy is "due"
// again on the next run regardless of nominal cadence (the
// on_fail_retry rule).
LastPassAt time.Time `json:"last_pass_at,omitempty"`
// LastFailAt is the run-start timestamp of the most recent run that
// evaluated this policy and produced StatusFail.
LastFailAt time.Time `json:"last_fail_at,omitempty"`
// LastRunStatus is the terminal status of the most recent
// evaluation. One of: pass, fail, error, skip, na, waived. Empty
// when this is a freshly-allocated state with no run history.
LastRunStatus PolicyStatus `json:"last_run_status,omitempty"`
// LastPeriodID is the period_id that the most recent evaluation
// belongs to. Carry-forward results reference this period via the
// envelope under LastEnvelopeRef.
LastPeriodID string `json:"last_period_id,omitempty"`
// LastRunID is the run_id of the most recent evaluation. The
// concurrent-write rule uses it as a tiebreaker when two runs
// share LastRunAt to the second.
LastRunID string `json:"last_run_id,omitempty"`
// LastPolicyHash is the SHA-256 of the canonicalized policy spec
// at the time of the most recent evaluation. A bundle update that
// changes the policy text invalidates this hash, marking the
// policy due on the next run regardless of cadence. The actual
// hash for the current run is computed at plan time via
// PolicyContentHash.
LastPolicyHash string `json:"last_policy_hash,omitempty"`
// LastEnvelopeRef is the run-relative path of the signed evidence
// envelope produced by the most recent evaluation. Carry-forward
// results emit a reference to this path so an auditor can
// hash-verify the original envelope independently.
LastEnvelopeRef string `json:"last_envelope_ref,omitempty"`
// NextDueAt is the wall-clock time after which the policy is
// considered due again under its configured cadence. Pre-computed
// at end of each run so the next planner pass is a single field
// read per policy. For "continuous" / "every: 0s" cadences this
// is the zero time (always due).
NextDueAt time.Time `json:"next_due_at,omitempty"`
// ConfiguredCadence is the cadence string in effect at the most
// recent evaluation ("daily", "every: 6h", etc.). Captured so a
// subsequent run can detect a configuration change and re-
// evaluate even when the time-since-last-pass would suggest
// otherwise. Currently informational; the planner gates on
// LastPolicyHash for content changes.
ConfiguredCadence string `json:"configured_cadence,omitempty"`
}
PolicyState is the per-policy operational record kept in the vault at state/{framework}/policies/{policy_id}.json. It is mutable scheduling state — never part of any signed manifest, never an audit deliverable, never trusted by an auditor (signed envelopes are the trust anchor).
The state's only consumer is the planner, which uses it to decide whether a policy is due to evaluate in the current run. Loss of a state shard is recoverable: the planner treats a missing shard as "first run" and evaluates the policy. The shard is rewritten after every evaluation.
See docs/architecture/11-cadence-model.md for the model.
func (*PolicyState) IsFirstRun ¶ added in v0.21.0
func (p *PolicyState) IsFirstRun() bool
IsFirstRun reports whether this policy has never been evaluated. The planner uses this to emit the first-run warning and to mark a policy as immediately due regardless of cadence.
type PolicyStatus ¶
type PolicyStatus string
PolicyStatus is the per-policy outcome of a run.
const ( StatusPass PolicyStatus = "pass" StatusFail PolicyStatus = "fail" StatusSkip PolicyStatus = "skip" StatusError PolicyStatus = "error" StatusNA PolicyStatus = "na" StatusWaived PolicyStatus = "waived" StatusCarriedForward PolicyStatus = "carried_forward" )
PolicyStatus values. `pass`/`fail` are the rule outcomes; `skip` / `error` / `na` / `waived` are evaluator/exception-driven states. `carried_forward` indicates the policy was NOT evaluated in this run — the result references a prior signed envelope. See docs/architecture/11-cadence-model.md §Carry-forward.
type Repository ¶
type Repository struct {
Provider string `json:"provider"`
NameSlug string `json:"name_slug"`
URL string `json:"url,omitempty"`
}
Repository is git-repo identity. Every field listed here is already public via the git remote URL.
type Rule ¶
Rule is the evaluation logic for a policy. Implementations may be hand-written Go, Rego (run via OPA), or a YAML DSL transpiled to Rego. Rules are pure functions over RuleInput — no I/O permitted.
type RuleInput ¶
type RuleInput struct {
PolicyID string
Slots map[string][]EvidenceRecord
Params map[string]any
Now time.Time
}
RuleInput is the read-only context handed to a rule per policy evaluation. Records arrive grouped by slot name.
type RuleResult ¶
type RuleResult struct {
Status PolicyStatus
Violations []Violation
Diag map[string]any
}
RuleResult is what a rule returns to the evaluator. Lives vault-side; the aggregator (L6) projects this into the privacy-bounded AggregatedPolicy that crosses the boundary.
type RunSummary ¶
type RunSummary struct {
PoliciesTotal int `json:"policies_total"`
PoliciesPassed int `json:"policies_passed"`
PoliciesFailed int `json:"policies_failed"`
PoliciesSkipped int `json:"policies_skipped"`
PoliciesError int `json:"policies_error"`
PoliciesNA int `json:"policies_na"`
PoliciesWaived int `json:"policies_waived"`
ComplianceScore float64 `json:"compliance_score"`
}
RunSummary is the counts-only run-level summary. ComplianceScore is the applicable-pass ratio computed in the aggregator: (policies_passed + policies_waived) / (policies_total - policies_skipped - policies_na). Skipped and N/A policies are removed from the denominator so they don't drag the score down; waived policies count toward the numerator on the basis that an accepted exception is operationally equivalent to a pass.
type Severity ¶
type Severity string
Severity is the policy's display severity. Set on the policy spec; a rule cannot override it. If a single policy needs variable severity, split it into multiple policies.
type Slot ¶
type Slot struct {
Accepts []string
Cardinality SlotCardinality
Required bool
Description string
}
Slot is a named typed input on a policy — the interface between the policy and the source plugins that fulfill it.
Accepts lists every evidence type that satisfies this slot. The planner binds a source to the slot when source.Emits() shares at least one type with Accepts; multiple bindings can target the same slot (subject to Cardinality) and may emit different types from the Accepts list. Rules receive evidence grouped by slot name and may switch on record.Type when behavior differs per type.
A slot listing more than one type is how cross-cloud / cross-source substitutability is expressed: an "object storage encrypted at rest" policy lists {s3_bucket, gcs_bucket, azure_blob_container} and is satisfied by any source that emits any of them — no policy fork, no source-side LCD payload, no normalization step. See docs/architecture/03-policy-spec.md §Slots.
type SlotCardinality ¶
type SlotCardinality string
SlotCardinality declares how many sources a slot may bind.
const ( SlotExactlyOne SlotCardinality = "exactly-one" SlotAtMostOne SlotCardinality = "at-most-one" SlotOneOrMore SlotCardinality = "one-or-more" SlotOptional SlotCardinality = "optional" )
SlotCardinality values. See 03-policy-spec.md §Slots for the project-binding rules each cardinality imposes.
type SlotRequest ¶ added in v0.19.0
type SlotRequest struct {
PolicyID string
AcceptedTypes []string
SlotName string
Params map[string]any
}
SlotRequest is the per-binding call into a plugin's Collect.
PolicyID is for diagnostics only — plugins must not branch behavior on it. AcceptedTypes is the intersection of the slot's Accepts list with the plugin's Emits(); the plugin returns records of any AcceptedTypes element (typically just one, since most plugins emit a single type). The planner enforces non-empty intersection at plan time, so AcceptedTypes is always at least one element on a real invocation. Params carries optional per-binding slot_params from the project config (rare; most bindings have no params).
func (SlotRequest) Accepts ¶ added in v0.20.4
func (r SlotRequest) Accepts(typeID string) bool
Accepts reports whether typeID is one of the slot's accepted evidence types. Source plugins use it to dispatch on which of their emitted types the slot actually wants.
type SourcePlugin ¶
type SourcePlugin interface {
ID() string
Emits() []string
Init(ctx context.Context, cfg map[string]any) error
Collect(ctx context.Context, req SlotRequest) ([]EvidenceRecord, error)
}
SourcePlugin produces EvidenceRecords for slots it can fulfill. Shipped plugins are compiled in; project-local plugins under .sigcomply/plugins/ are compiled in by `sigcomply build` (M16).
Implementations must:
- Sort emitted records by ID lexicographically before returning from Collect — keeps envelope bytes stable across runs when source state is stable.
- Set IdentityKey on EvidenceRecord when the evidence type has a meaningful cross-source identity (see 03-policy-spec.md §Cross-source dedup).
- Avoid embedding wall-clock timestamps in record payloads beyond what the source itself provides; use EvidenceRecord.CollectedAt for fetch time.
type SubmissionPayload ¶
type SubmissionPayload struct {
Schema string `json:"schema"`
RunID string `json:"run_id"`
Framework string `json:"framework"`
PeriodID string `json:"period_id"`
CommitSHA string `json:"commit_sha"`
CommitTime time.Time `json:"commit_time"`
Branch string `json:"branch"`
Repository Repository `json:"repository"`
Environment CIEnvironment `json:"environment"`
CLIVersion string `json:"cli_version"`
StartedAt time.Time `json:"started_at"`
CompletedAt time.Time `json:"completed_at"`
Summary RunSummary `json:"summary"`
Policies []AggregatedPolicy `json:"policies"`
}
SubmissionPayload is the wire format crossing the aggregation boundary from the customer environment to the cloud. Every field is concretely typed and represents either a count, an enum status, or already-public metadata.
SECURITY: This type is the structural privacy guarantee of the non-custodial architecture. Adding any field that could carry resource identity (ARNs, emails, IDs, file hashes, hostnames) is a non-custodial regression. Required for any such change:
- Written justification on the PR.
- Demonstration that the field cannot carry identity in any deployment.
- Review by >=2 maintainers including the security owner.
- Schema-version bump (sigcomply.cloud.v2).
The reflection test in cloud_test.go enforces "no freeform fields" structurally — adding interface{}, json.RawMessage, or map[string]any (transitively) will fail the build.
type Vault ¶
type Vault interface {
Init(ctx context.Context) error
PutEnvelope(ctx context.Context, path string, e *Envelope) error
PutJSON(ctx context.Context, path string, body any) error
PutBinary(ctx context.Context, path string, body []byte, meta map[string]string) error
GetBinary(ctx context.Context, path string) ([]byte, error)
List(ctx context.Context, prefix string) ([]string, error)
}
Vault is the customer-side persistence layer. Append-only per run; the CLI writes, auditors and dashboards read. Implementations are backend-specific (local, s3, gcs, azure_blob) but all conform to this interface.
The CLI never reads from the vault during the same run — vault is one-way for write-side flows.