core

package
v0.20.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

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

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

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"`
}

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.

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 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 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 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
}

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 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"
)

PolicyStatus values. `pass`/`fail` are the rule outcomes; `skip` / `error` / `na` / `waived` are evaluator/exception-driven states.

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

type Rule interface {
	ID() string
	Evaluate(ctx context.Context, in RuleInput) (RuleResult, error)
}

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 policies_passed / policies_total ratio, computed in the aggregator.

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.

const (
	SeverityInfo     Severity = "info"
	SeverityLow      Severity = "low"
	SeverityMedium   Severity = "medium"
	SeverityHigh     Severity = "high"
	SeverityCritical Severity = "critical"
)

Severity values, in ascending order of urgency.

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:

  1. Sort emitted records by ID lexicographically before returning from Collect — keeps envelope bytes stable across runs when source state is stable.
  2. Set IdentityKey on EvidenceRecord when the evidence type has a meaningful cross-source identity (see 03-policy-spec.md §Cross-source dedup).
  3. 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:

  1. Written justification on the PR.
  2. Demonstration that the field cannot carry identity in any deployment.
  3. Review by >=2 maintainers including the security owner.
  4. 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.

type Violation

type Violation struct {
	ResourceID string
	Reason     string
	Details    map[string]any
}

Violation is one record-level failure produced by a rule. Lives vault-side only — never crosses the aggregation boundary.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL