diff

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 13, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package diff computes a typed ChangeSet between two versions of a sas.Architecture: which nodes, relationships, and boundaries were added, removed, or modified, and which specific fields changed on each.

Diff is a pure structural comparison. It classifies no impact and makes no judgment about significance — turning a ChangeSet into a semantic classification (new external dependency, authentication mechanism change, entitlement expansion, ...) is a separate, later concern layered on top of this package.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Assessment

type Assessment struct {
	ID         string    `json:"id"`
	BaselineID string    `json:"baselineId"`
	Decision   string    `json:"decision"`
	Reviewer   string    `json:"reviewer"`
	DecidedAt  time.Time `json:"decidedAt"`

	// Evidence references what the decision was based on, e.g. specific
	// ChangeImpact entries, ticket links, or an external review document.
	Evidence []string `json:"evidence,omitempty"`

	Notes string `json:"notes,omitempty"`
}

Assessment is a recorded human decision about a proposed architecture change relative to a Baseline, with the evidence it was based on.

Decision is a plain string, not a closed enum, deliberately: the vocabulary of valid decisions is a compliance-profile concern (the FedRAMP profile's three-outcome NO_REVIEW_REQUIRED / CHANGE_ASSESSMENT_REQUIRED / POTENTIAL_SIGNIFICANT_CHANGE vocabulary is just one profile's), and compliance logic lives in profiles, not core — the same principle that keeps validate.Profile rules out of the sas package itself. A profile package defines its own typed decision constants and is responsible for only ever writing one of them here.

type Baseline

type Baseline struct {
	ID           string           `json:"id"`
	Name         string           `json:"name"`
	Architecture sas.Architecture `json:"architecture"`
	ApprovedAt   time.Time        `json:"approvedAt"`
	ApprovedBy   string           `json:"approvedBy"`
}

Baseline is a named, approved architecture version. Once approved, a Baseline is immutable by convention: callers must not mutate Architecture in place after construction, the same way a Git tag names a commit rather than a mutable ref. SAS does not enforce this at the language level (no exported struct in this codebase does), but every Baseline consumer treats it as a historical fact, never a working copy.

type Change

type Change struct {
	Kind        ChangeKind   `json:"kind"`
	ElementType ElementType  `json:"elementType"`
	ElementID   string       `json:"elementId"`
	Deltas      []FieldDelta `json:"deltas,omitempty"`
}

Change is a single typed fact about how the architecture changed: one element, one kind of change, and (for modifications) the specific fields that differ.

type ChangeImpact

type ChangeImpact struct {
	Impacts []Impact `json:"impacts"`
}

ChangeImpact is every Impact derived from a ChangeSet, in the same stable order as the ChangeSet's own Changes.

func Classify

func Classify(cs ChangeSet, proposed *sas.Architecture) ChangeImpact

Classify derives the semantic ChangeImpact from a ChangeSet. proposed supplies the full field values for elements diff didn't need to materialize on Added changes (e.g. a new relationship's target node kind, or its full CrossesBoundaries list).

type ChangeKind

type ChangeKind string

ChangeKind classifies what happened to an element between the base and proposed architecture.

const (
	ChangeKindNodeAdded    ChangeKind = "node_added"
	ChangeKindNodeRemoved  ChangeKind = "node_removed"
	ChangeKindNodeModified ChangeKind = "node_modified"

	// ChangeKindBoundaryMembershipChanged is reported separately from
	// ChangeKindNodeModified even though membership lives on Node, since
	// "this node now belongs to a new boundary" is the specific fact a
	// change-impact classifier (new boundary crossing) needs to find
	// without parsing a generic field diff.
	ChangeKindBoundaryMembershipChanged ChangeKind = "boundary_membership_changed"

	ChangeKindRelationshipAdded    ChangeKind = "relationship_added"
	ChangeKindRelationshipRemoved  ChangeKind = "relationship_removed"
	ChangeKindRelationshipModified ChangeKind = "relationship_modified"

	ChangeKindBoundaryAdded    ChangeKind = "boundary_added"
	ChangeKindBoundaryRemoved  ChangeKind = "boundary_removed"
	ChangeKindBoundaryModified ChangeKind = "boundary_modified"
)

type ChangeReview

type ChangeReview struct {
	ID         string           `json:"id"`
	Baseline   Baseline         `json:"baseline"`
	Proposed   sas.Architecture `json:"proposed"`
	Assessment *Assessment      `json:"assessment,omitempty"`
}

ChangeReview ties an approved Baseline to a proposed Architecture and the human Assessment of the change between them — the {baseline, proposed, assessment} triple a release references. Assessment is nil until a human records a decision; a ChangeReview is a legitimate, useful value before that (its ChangeSet/Impact can already be computed and circulated for review).

func (ChangeReview) ChangeSet

func (r ChangeReview) ChangeSet() ChangeSet

ChangeSet computes the diff between this review's baseline and proposed architecture.

func (ChangeReview) Impact

func (r ChangeReview) Impact() ChangeImpact

Impact computes the semantic classification of this review's change.

type ChangeSet

type ChangeSet struct {
	Changes []Change `json:"changes"`
}

ChangeSet is every Change between a base and proposed Architecture, in a stable order (nodes, then relationships, then boundaries; within each, sorted by element ID).

func Diff

func Diff(base, proposed *sas.Architecture) ChangeSet

Diff computes the ChangeSet from base to proposed: what an author would need to review to understand how the architecture changed.

type ElementType

type ElementType string

ElementType names which part of the graph a Change applies to.

const (
	ElementTypeNode         ElementType = "node"
	ElementTypeRelationship ElementType = "relationship"
	ElementTypeBoundary     ElementType = "boundary"
)

type FieldDelta

type FieldDelta struct {
	Field  string `json:"field"`
	Before string `json:"before,omitempty"`
	After  string `json:"after,omitempty"`
}

FieldDelta names a single field that differs between the base and proposed element, with human-readable before/after values. Field is a dotted path (e.g. "transport.encryption") so callers can filter or match on the specific fact that changed rather than parsing prose. Before/After are omitted (empty string) when the field was unset on that side.

type Impact

type Impact struct {
	Kind               ImpactKind  `json:"kind"`
	ElementType        ElementType `json:"elementType"`
	ElementID          string      `json:"elementId"`
	AffectedBoundaries []string    `json:"affectedBoundaries,omitempty"`
	Detail             string      `json:"detail"`
}

Impact is a single semantic classification of one Change, with enough detail for a human reviewer or compliance profile to act on without re-deriving it from the raw FieldDelta.

type ImpactKind

type ImpactKind string

ImpactKind classifies the security/compliance-relevant meaning of a Change — the semantic fact a human reviewer or a compliance profile actually cares about, as opposed to ChangeKind's structural fact (what was added/removed/modified).

const (
	// ImpactKindNewExternalDependency: a new relationship to (or a new
	// node that is) an external_service.
	ImpactKindNewExternalDependency ImpactKind = "new_external_dependency"

	// ImpactKindAuthnMechanismChanged: the identity a relationship's
	// caller acts as changed.
	ImpactKindAuthnMechanismChanged ImpactKind = "authn_mechanism_changed"

	// ImpactKindEntitlementExpansion: a relationship gained a write
	// operation (create/update/delete/administer) it did not have
	// before, or gained new authorization entitlements.
	ImpactKindEntitlementExpansion ImpactKind = "entitlement_expansion"

	// ImpactKindNewBoundaryCrossing: a relationship now crosses a
	// boundary it did not cross before (including a brand new
	// relationship that crosses one from the start).
	ImpactKindNewBoundaryCrossing ImpactKind = "new_boundary_crossing"

	// ImpactKindDataClassificationChange: the data classifications
	// carried by a relationship changed.
	ImpactKindDataClassificationChange ImpactKind = "data_classification_change"

	// ImpactKindComputeModelChanged: a node's underlying Technology
	// changed, e.g. compute.instance moving from ecs to lambda.
	ImpactKindComputeModelChanged ImpactKind = "compute_model_changed"
)

Directories

Path Synopsis
Package fedramp is a compliance profile layered on top of the generic diff package: it classifies a diff.ChangeImpact into FedRAMP's three-outcome change-assessment vocabulary (no review required, change assessment required, potential significant change).
Package fedramp is a compliance profile layered on top of the generic diff package: it classifies a diff.ChangeImpact into FedRAMP's three-outcome change-assessment vocabulary (no review required, change assessment required, potential significant change).

Jump to

Keyboard shortcuts

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