50 KiB
Package-boundary migration record
Status: Active implementation record. Decision: Mulga ADR-0001 — Spinifex Package Boundary and Layout. Scope: Spinifex source layout only. This record does not establish a new architecture decision, expand a customer-facing interface, or claim that the current implementation conforms to the target layout.
Purpose
This document records the implementation sequence for ADR-0001 in this repository. The ADR owns the target layout and dependency rules; this record captures the source-level entry-point inventory and the evidence needed for each narrow structural slice.
The migration proceeds on one long-lived refactor branch. Each commit remains small, independently buildable and reviewable; that does not require one pull request per package move.
Baseline
The inventory below was taken from Spinifex commit
ecef5e4d2f793b4cf2c96d0a43d0a1ab37be3eed, the revision pinned by Mulga when
ADR-0001 was accepted. It records ownership standing, not a promise that a
binary or script is AWS-compatible or supported beyond its documented scope.
Entry-point and automation inventory
Product operator and delivery entry points
| Current path | Standing | Target ownership | Migration rule |
|---|---|---|---|
cmd/spinifex (spx) |
Supported operator process | Thin main; command assembly in spinifex/operator/cli and individual supported use cases in spinifex/operator/* |
Preserve binary and supported command compatibility. The CLI must reach a domain through an explicit capability, never its private state. |
cmd/installer |
Delivery executable | Thin main; interactive, unattended and host-installation work in spinifex/operator/installer |
Preserve installation behaviour while separating executable startup from delivery logic. It is not, merely by existing, the permanent administration interface. |
cmd/spinifex/cmd and cmd/installer/* are presently implementation-bearing
trees, not thin entry points. They are not moved until their individual
receiving owners and test seams are selected.
Guest and named-role entry points
| Current path | Standing | Target ownership | Evidence of role boundary |
|---|---|---|---|
cmd/ecs-agent |
ECS guest agent | Thin main; spinifex/agents/ecs |
Baked into ECS node images; communicates with the control plane through the AWS gateway, not NATS. |
cmd/rds-agent |
RDS guest agent | Thin main; spinifex/agents/rds |
Runs in an RDS guest, handles bootstrap and engine directives through the gateway. |
cmd/lb-agent |
ELBv2 guest agent | Thin main; spinifex/agents/elbv2 |
Included in the load-balancer microVM and controls its local data plane. |
cmd/eks-token-webhook |
EKS control-plane guest role | Thin main; spinifex/agents/eks/tokenwebhook |
Baked into the EKS node image as the Kubernetes TokenReview webhook. |
cmd/eks-gateway-fetch |
EKS control-plane guest helper | Thin main; spinifex/agents/eks/gatewayfetch |
Fetches recovery and addon state through the AWS gateway. |
cmd/eks-gateway-publish |
EKS control-plane guest helper | Thin main; spinifex/agents/eks/gatewaypublish |
Relays bootstrap and state reports through the AWS gateway. |
cmd/eks-webhook-cert |
EKS image-resident certificate helper | Thin main; spinifex/agents/eks/webhookcert |
Invoked by EKS image scripts to create/reuse webhook serving certificates. |
cmd/eks-konnectivity-cert |
EKS image-resident certificate helper | Thin main; spinifex/agents/eks/konnectivitycert |
Invoked by EKS image scripts to create/reuse Konnectivity serving certificates. |
cmd/ecr-credential-provider |
EKS node integration | Thin main; spinifex/agents/eks/credentialprovider |
Kubelet exec credential provider baked into EKS images; it is not ECR control-plane ownership. |
No common agent package is introduced by this inventory. Shared mechanisms are considered only when the existing role and least-privilege boundaries remain intact; ADR-0001 explicitly defers that design.
Development and qualification entry points
| Current path | Standing | Target ownership | Rule |
|---|---|---|---|
cmd/aws-model-coverage |
Qualification generator | Thin main; reusable code in internal/tooling |
Produces the dispatch-versus-model inventory; never imported by product packages. |
cmd/dhcptest |
Development diagnostic | Thin main; reusable code in internal/tooling if extraction is useful |
It is a DHCP probe, not a supported spx admin command. |
cmd/spx-loadgen |
Qualification/load tool | Thin main; reusable code in internal/testkit |
It drives test load and is not shipped to nodes. |
tests/e2e/*/cmd/*, tests/bench/*/cmd/* |
Test and benchmark-private tools | Remain test-private | They are invoked by a test or benchmark harness, not a product process. |
docs/terraform-workbooks/demo-app/main.go |
Demonstration workload | Remain with the workbook | It is neither a Spinifex executable nor a product package. |
Automation standing
| Path class | Standing | Rule during migration |
|---|---|---|
.github/scripts/ |
CI-private qualification automation | Keep at the module root; the invoking workflow owns the evidence scope. |
build/, images/, scripts/images/, image build and publish scripts |
Delivery and guest-image inputs | Keep at the module root. In-guest helpers stay with their image; do not relocate shell sources into Go packages. |
scripts/setup.sh, setup-ovn.sh, install-node.sh, node-reset.sh, uninstall-spx.sh |
Transitional delivery and documented host-operation mechanics | Keep at the module root. They may implement a published procedure but are not an enduring public administration API solely because they are installed on a node. |
scripts/dev-env/, scripts/demo/, benchmarks, diagnostics and Terraform experiments |
Development or exploratory automation | Keep at the module root; they are not customer-facing contracts. |
scripts/check-coverage.sh, diff-coverage.sh, run-gate.sh, sync-aws-models.sh and test harness scripts |
Repository and qualification automation | Keep at the module root; their caller defines the contract and evidence. |
First source move — ARN
The first source move is the cohesive ARN leaf package:
- old import path:
github.com/mulgadc/spinifex/spinifex/arn - target import path:
github.com/mulgadc/spinifex/spinifex/foundation/aws/arn
Source commit 91ac70e29 moves the ten package files and updates all forty-four
Go importers. It changes no behaviour and leaves no forwarding package.
Verification passed with an isolated Go module/build cache:
go test ./spinifex/foundation/aws/arngo testfor the fourteen packages directly importing ARN- a Go-source search for the old import path returned no matches
git diff --check
The inventory was intentionally committed before this move so a later thin-main refactor cannot silently choose an owner by convenience.
Second source move — AWS filters
The second source move removes the generic filterutil location and name:
- old import path:
github.com/mulgadc/spinifex/spinifex/filterutil - target import path:
github.com/mulgadc/spinifex/spinifex/foundation/aws/filters
Source commit e707be942 moves the two package files, renames the Go package
to filters, and updates twenty-eight importing files. Callers use the
explicit import alias awsfilters: many filter implementations already hold
a local filters value, and the alias prevents a package-name collision
without changing that local state or any filter behaviour.
Verification passed with an isolated Go module/build cache:
go test ./spinifex/foundation/aws/filtersgo testfor the seventeen direct caller packages- a Go-source search for the old import path returned no matches
git diff --check
Third source move — AWS Query parser
The third source move names the protocol concern rather than the first service that happened to use it:
- old import path:
github.com/mulgadc/spinifex/spinifex/awsec2query - target import path:
github.com/mulgadc/spinifex/spinifex/ingress/aws/query
Source commit caaf98d9e moves the two parser files, renames the Go package to
query, and updates thirteen importing files. The parser is used across EC2,
IAM, STS, ECS, ECR, ELBv2 and RDS, but owns only AWS Query wire decoding and no
service action or resource semantics.
Verification passed with an isolated Go module/build cache:
go test ./spinifex/ingress/aws/querygo test -run '^$'for six direct caller packages- a Go-source search for the old import path returned no matches
git diff --check
A broad go test run over those caller packages was stopped after two minutes
without output. It is not recorded as a passing test; the normal full suite
remains CI evidence for the branch.
Subsequent source moves
The following slices follow the same rule as the first three: each is a
structural move with import rewrites, no compatibility shim, focused package
and direct-caller validation, and git diff --check. They are recorded here
while the branch is in flight; they do not describe the umbrella repository's
main until its Spinifex gitlink is updated.
| Source commit | Old path | New path | Finding or boundary recorded |
|---|---|---|---|
04b41a62c |
spinifex/idempotency |
spinifex/foundation/lifecycle/idempotency |
Generic request coalescing is lifecycle infrastructure, not a domain owner. |
25fa01a3d |
spinifex/preflight |
spinifex/bootstrap/preflight |
Startup validation is bootstrap input, not a generic service. |
681fccc61 |
spinifex/systemd |
spinifex/operator/host/systemd |
Host unit generation and reconciliation are operator-host work. |
23ca5d8aa |
spinifex/resource |
spinifex/foundation/lifecycle/resource |
Resource metadata is a generic lifecycle primitive. |
7a3c8de07 |
spinifex/nbd |
spinifex/runtime/compute/nbd |
NBD process control is node-local compute runtime. |
ea65616be |
spinifex/hostdns |
spinifex/runtime/host/dns |
Host resolver integration is runtime host work. |
d80803807 |
spinifex/qmp |
spinifex/runtime/compute/qmp |
QMP is local VM runtime control. |
41e2c1f10 |
spinifex/gpu |
spinifex/runtime/compute/gpu |
GPU discovery and attachment are local compute runtime work. |
d78246d05 |
spinifex/instancetypes |
spinifex/domains/ec2/instancetypes |
AWS-visible instance-type semantics belong to EC2. |
b2ce46124 |
spinifex/service |
spinifex/runtime/service |
The named-role catalogue is runtime composition. |
573ee6761 |
spinifex/loadgen |
internal/testkit/loadgen |
Load generation is qualification support, not product code. |
afdb6618c |
spinifex/otelsetup |
spinifex/foundation/telemetry |
Spinifex instrumentation primitives are shared telemetry foundation. |
956fe1490 |
spinifex/awserrors |
spinifex/foundation/aws/errors |
AWS error vocabulary is shared AWS foundation. |
cbbf252e6 |
spinifex/testutil |
internal/testkit |
Test doubles remain compiler-private and cannot become application dependencies. |
0c2d64413 |
spinifex/vm |
spinifex/runtime/compute/vm |
VM lifecycle is node-local compute runtime, not EC2 API ownership. |
a74adc48b |
spinifex/ebsmetadata |
spinifex/domains/ec2/ebs/metadata |
EBS API metadata remains EC2-domain state. |
94ddc91a1 |
spinifex/ebsprovider |
spinifex/providers/ebs |
The provider contract and conformance suite are replaceable storage adapters. |
3c1bce1eb |
spinifex/cloud/oci |
spinifex/providers/cloud/oci |
OCI access is a replaceable cloud-provider adapter. |
56970d079 |
spinifex/services/nats |
spinifex/runtime/roles/nats |
NATS process startup is a named runtime role. |
d87326f64 |
spinifex/network/listenerinventory |
internal/testkit/listenerinventory |
Listener inventory is test-only qualification support. |
4d4875b13 |
spinifex/services/spinifexui |
spinifex/runtime/roles/spinifexui |
The web UI is a named runtime role, not a logical AWS domain. |
f39bc64c9 |
spinifex/admin listener helpers |
spinifex/foundation/netaddr |
Listener-address parsing is a small shared network primitive. |
9e8e889fb |
spinifex/services/qemunbdd |
spinifex/runtime/roles/qemunbdd |
QEMU-NBD provider process startup is a runtime role. |
3494ae131 |
spinifex/services/qmpcollector |
spinifex/runtime/roles/qmpcollector |
QMP collection is a named runtime role. |
f64931546 |
spinifex/services/spinifex |
spinifex/runtime/roles/spinifex |
The core daemon executable role is runtime composition. |
57f238a0c |
spinifex/tags |
spinifex/foundation/aws/tags |
System-tag vocabulary is shared AWS foundation. |
7a6b00728, 186ef7ebc |
spinifex/kvutil |
spinifex/foundation/state/kvutil |
Replica policy was made explicit before moving generic KV utilities to state foundation. |
57f9d2ccc |
spinifex/kvstore |
spinifex/foundation/state/kvstore |
Generic KV storage mechanics are state foundation. |
247e52ba3 |
spinifex/reconciler |
spinifex/foundation/lifecycle/reconciler |
Generic reconciliation mechanics are lifecycle foundation. |
b1d0eba89 |
inline KV migration mechanics | spinifex/foundation/state/migrate |
KV migration is a reusable state concern. |
967f6904a |
spinifex/kvlease |
spinifex/foundation/state/kvlease |
Leases are state foundation, not a resource-domain owner. |
248f0e005, 8c4af3030 |
spinifex/formation |
spinifex/runtime/formation |
Formation owns its protocol payloads and remains runtime membership/bootstrap work. |
b8b97279c, c0c64cd53 |
spinifex/instancecache |
spinifex/runtime/compute/cache |
Cache policy is decoupled from callers before becoming node-local compute runtime. |
aa0c36ff4 |
spinifex/types/ec2.go |
contracts/ec2/v1 |
The EC2 instance-command subject and JSON payload are an explicit versioned cross-process contract; commands_test.go is its compatibility evidence. |
c239fd897 |
spinifex/types/eni.go |
spinifex/runtime/compute/vm/eni_requests.go |
PCIe hot-plug slot allocation is mutex-bearing, per-VM runtime state rather than a shared type or wire contract; record_test.go preserves its restart semantics. |
6d6275e78 |
spinifex/types/cluster.go (NodeHealthResponse) |
contracts/cluster/v1/health.go |
Node health is a versioned cluster control-plane representation shared by the per-node NATS route and daemon HTTPS /health; health_test.go pins both wire forms. |
53a614717 |
spinifex/types/cluster.go (SharedClusterData) |
spinifex/daemon/config_hash.go |
Shared-config hash input is daemon-local implementation data; focused config-hash tests preserve deterministic, shared-only semantics. |
78fd017e0 |
spinifex/types/telemetry.go (GuestTelemetryMeta) |
contracts/telemetry/v1/guest_meta.go |
QMP collector sidecar JSON is a versioned file contract between VM runtime and telemetry role; guest_meta_test.go pins its filename and payload. |
4b35a2a33 |
spinifex/types/node.go (NodeVMsResponse, VMInfo, VMGPUInfo) |
contracts/cluster/v1/node_vms.go |
VM inventory is a versioned cluster fan-out payload used by SPX CLI and EKS host lookup; node_vms_test.go pins its subject and JSON shape. |
08bd335f0 |
spinifex/types/node.go (NodeStatusResponse, capacity and GPU inventory) |
contracts/cluster/v1/status.go |
Node status is a versioned fan-out observation contract for operator inspection and EC2/EKS scheduling consumers; status_test.go pins its subject and JSON shape. |
f4cb550c9 |
spinifex/types/ebs.go (GP3 policy constants) |
spinifex/domains/ec2/ebs/policy/gp3.go |
The supported GP3 product envelope is EC2 EBS domain policy, not generic runtime or Viperblockd wire state; gp3_test.go pins the deployed values. |
adb55de33 |
spinifex/types/ebs.go (NBDTransport) |
spinifex/services/viperblockd/nbd_transport.go |
NBD endpoint transport selection is Viperblockd-local delivery configuration, not generic EBS state or a provider contract; nbd_transport_test.go pins the socket and TCP forms. |
94a6e7af2 |
spinifex/types/ebs.go (EBSConfigUpdateRequest, EBSConfigUpdateResponse) |
contracts/viperblockd/legacy/v1/config_update.go |
Legacy configuration updates have deployed queue and volume-addressed NATS routes; the versioned compatibility contract is expressly transitional and separate from providers/ebs. |
b975f1ba9 |
Remaining spinifex/types/ebs.go payloads |
runtime/compute/vm/ebs_requests.go and contracts/viperblockd/legacy/v1/volume.go |
The mutex-bearing attachment collection is VM-owned; deployed mount, unmount and delete routes plus their JSON payloads are versioned Viperblockd legacy compatibility. Contract tests pin every route and JSON shape. |
61cf833aa |
spinifex/cloud/exoscale |
spinifex/providers/cloud/exoscale |
Exoscale CLI access is a replaceable external-cloud adapter. The source move rewrites its four Exonet callers and preserves its adapter tests and CLI boundary. |
dbc62562c |
spinifex/objectstore |
spinifex/providers/objectstore |
The generic S3-compatible client is a replaceable object-storage adapter, not S3 resource authority. The mechanical move rewrites all direct callers; its focused suite and caller compilation passed. |
f11922986 |
spinifex/config |
spinifex/bootstrap/config |
Root configuration parsing belongs to bootstrap. Its package API is unchanged; package tests and regular, integration, E2E and benchmark caller compilation passed. |
aa4b0b1bb |
spinifex/paging |
spinifex/foundation/aws/paging |
Opaque listing tokens, deterministic slicing and EC2 pagination validation are shared AWS protocol infrastructure rather than EC2 resource authority. The move rewrites all five EC2 callers; focused package tests, direct caller compilation and tagged integration compilation passed. |
6ac02a886 |
spinifex/clustersize |
spinifex/foundation/state/clustersize |
The declared cluster size and its fail-closed JetStream/KV replica policy are shared state-tier infrastructure, not a resource-domain owner. Focused package tests, all direct caller compilation, integration and E2E-tagged harness compilation passed. |
93084043a |
spinifex/handlers/ecr |
spinifex/domains/ecr |
ECR repository metadata, blob semantics and lifecycle rules are ECR domain ownership. The full domain suite, direct callers and tagged integration callers passed. |
51b5c55b9 |
spinifex/gateway/ecrapi |
spinifex/domains/ecr/awsapi |
AWS JSON 1.1 action inventory, validation, resource-scope derivation and NATS-backed action handlers are ECR action-adapter ownership. Focused, gateway and tagged integration validation passed. |
5e7311eb2 |
spinifex/gateway/ecr |
spinifex/domains/ecr/registry |
The OCI Distribution v2 protocol adapter is ECR data-plane ownership. Focused registry, gateway/AWS-gateway and tagged integration validation passed. |
474c07316 |
spinifex/gateway/ecrauth |
spinifex/domains/ecr/auth |
ECR token claims, issuer/verifier, encrypted signing-key persistence and rotation are ECR credential ownership. Focused, gateway/AWS-gateway and tagged integration validation passed. |
f59b40ad1 |
Gateway DescribeRepositories action semantics |
spinifex/domains/ecr/awsapi.DescribeRepositories |
Request validation, account scope, repository metadata lookup and AWS response projection are ECR AWS-action ownership. Gateway retains authenticated HTTP adaptation and response writing. Focused domain, gateway dispatch and tagged integration compilation passed. |
c558872e8 |
Gateway CreateRepository action semantics |
spinifex/domains/ecr/awsapi.CreateRepository |
Request decoding, input defaults and validation, duplicate detection, account-scoped metadata persistence and AWS response projection are ECR AWS-action ownership. Gateway retains authenticated HTTP adaptation and response writing. Focused domain, gateway lifecycle and tagged integration validation passed. |
a6b209b7b |
Gateway DeleteRepository action semantics |
spinifex/domains/ecr/awsapi.DeleteRepository |
Request validation, account scope, non-empty protection, forced deletion, metadata cascade and AWS response projection are ECR AWS-action ownership. Blob reclamation remains the separately documented GC concern. Focused domain, gateway lifecycle and tagged integration validation passed. |
7a5159366 |
Gateway PutImageTagMutability action |
spinifex/domains/ecr/awsapi.PutImageTagMutability |
This endpoint-free action is registered directly in the ECR action table rather than retained as a gateway wrapper. Request validation, account-scoped metadata update and AWS response construction are domain-adapter ownership; generic gateway auth and policy gating remain before dispatch. Focused domain, gateway and tagged integration validation passed. |
a2f6005d2 |
Gateway GetAuthorizationToken action response |
spinifex/domains/ecr/awsapi.GetAuthorizationToken |
Gateway retains canonical IAM/STS principal construction from authenticated context. The ECR adapter consumes a narrow token-issuer capability and owns mint-result handling, Docker AWS:<jwt> encoding and AWS response projection. Focused domain, real issuer/verifier gateway round-trip and tagged integration validation passed. |
ee4610a75 |
Gateway ListImages action semantics |
spinifex/domains/ecr/awsapi.ListImages |
The ECR AWS adapter consumes a narrow OCI image-catalog capability and owns request validation, account scope, tag-status projection and AWS response/error mapping. Gateway retains authenticated HTTP adaptation and supplies the configured registry. Focused domain, registry-backed gateway and tagged integration validation passed. |
b22b723a4 |
Gateway DescribeImages action semantics |
spinifex/domains/ecr/awsapi.DescribeImages |
The ECR AWS adapter now shares the image-catalog capability and catalog error mapping with ListImages, and owns image selection/detail projection. The accepted-but-unapplied filter field is explicitly retained as an unchanged compatibility gap. Focused domain, registry-backed gateway and tagged integration validation passed. |
deabaa300 |
Gateway BatchGetImage action semantics |
spinifex/domains/ecr/awsapi.BatchGetImage |
The ECR AWS adapter consumes a narrow manifest-reader capability and owns request validation, the 100-image cap, digest-over-tag selection and partial-failure response projection. Repository/account scope validation is now shared with ListImages and DescribeImages. Focused domain, registry-backed gateway and tagged integration validation passed. |
2542ce98e |
Gateway PutImage action semantics |
spinifex/domains/ecr/awsapi.PutImage |
The ECR AWS adapter consumes a narrow manifest-writer capability and owns request validation, tag/digest selection, AWS response projection and OCI manifest-store error translation. Gateway retains authenticated HTTP adaptation and supplies the configured registry. Focused domain, registry-backed gateway and tagged integration validation passed. |
7666ed208 |
Gateway BatchDeleteImage action semantics and residual ECR helpers |
spinifex/domains/ecr/awsapi.BatchDeleteImage, awsapi.ValidateRepositoryScope, gateway ecr_request.go |
The ECR adapter consumes a narrow image-deleter capability and owns batch deletion/partial-failure projection. Completion exposed scope validation still needed by lifecycle-preview adapters, which now calls the exported ECR adapter utility; generic HTTP JSON decoding moved to a gateway ECR adapter helper. Focused domain, image/lifecycle gateway and tagged integration validation passed. |
72c20bf78 |
Gateway lifecycle-preview evaluation and StartLifecyclePolicyPreview |
spinifex/domains/ecr/awsapi.EvaluateLifecyclePreview, StartLifecyclePolicyPreview |
Shared preview evaluation now consumes explicit policy-store and image-catalog capabilities, owns request/stored-policy resolution and lifecycle evaluation, and returns a reusable expiry set. Start preview is fully domain-owned; Get preview consumes the evaluator and retains only its response projection pending the next slice. Focused domain, lifecycle gateway and tagged integration validation passed. |
68945bbb1 |
Gateway GetLifecyclePolicyPreview response projection |
spinifex/domains/ecr/awsapi.GetLifecyclePolicyPreview |
Get preview now joins Start preview in the ECR adapter, sharing the synchronous evaluator and explicit policy-store/image-catalog capabilities. Gateway retains only authenticated HTTP/body adaptation and capability supply. Focused domain, lifecycle gateway and tagged integration validation passed. |
4c9f3d681 |
Gateway ECR image-action wrappers and residual JSON adapter | spinifex/domains/ecr/awsapi.RegistryActionService |
ListImages, DescribeImages, BatchGetImage, PutImage and BatchDeleteImage now dispatch through one composed registry-action capability after the generic gateway's authentication and policy gate. The composition root supplies narrow OCI capabilities; the operation inventory derives their implemented status from that capability. The obsolete gateway wrappers and JSON helper are removed. Focused domain, gateway, AWS-gateway and tagged integration validation passed. |
40e7b14ad |
Gateway lifecycle-preview wrappers | spinifex/domains/ecr/awsapi.LifecyclePreviewActionService |
StartLifecyclePolicyPreview and GetLifecyclePolicyPreview now dispatch through one composed policy-store-plus-image-catalog capability after generic authorization. Production reuses the registry's NATS metadata client; focused tests compose an in-memory metadata store. The obsolete wrappers are removed, and a missing composition fails closed rather than falling through to the raw action table. Focused domain, gateway, AWS-gateway and tagged integration validation passed. |
54f96ad78 |
Gateway CreateRepository, DescribeRepositories and DeleteRepository wrappers | spinifex/domains/ecr/awsapi.RepositoryActionService |
Repository actions now dispatch through one composed metadata-store-plus-endpoint-profile capability after generic authorization. The individual action adapters depend on a narrow repository metadata contract rather than constructing NATS clients themselves. The three obsolete wrappers are removed, and a missing composition fails closed. Focused domain, gateway, AWS-gateway and tagged integration validation passed. |
5ebbdcb53 |
Gateway GetAuthorizationToken wrapper and endpoint adapter | spinifex/domains/ecr/awsapi.AuthorizationTokenActionService |
GetAuthorizationToken now dispatches through a composed issuer-plus-endpoint capability after gateway constructs the canonical IAM/STS principal. The token subject remains gateway identity work; ECR retains credential response projection. The obsolete wrapper and endpoint adapter are removed, a missing action service fails closed, and an unavailable issuer retains the declared NotImplemented response. Focused domain, gateway, AWS-gateway and tagged integration validation passed. |
2b945ad88 |
spinifex/handlers/acm, spinifex/gateway/acm |
spinifex/domains/acm, spinifex/domains/acm/awsapi |
ACM certificate state, issuance and renewal are ACM-domain ownership; its AWS JSON/NATS request adapters live beside them. All nine adapters, including the previously inlined RequestCertificate path, now use domains/acm/awsapi; generic gateway retains only routing, request context, policy gating and response writing. Focused domain, adapter and gateway request tests plus direct-caller and tagged integration compilation passed. |
47c6b2fcf |
spinifex/gateway/bodyscope |
spinifex/ingress/aws/bodyscope |
Case-aware, ambiguity-safe extraction of AWS JSON request identifiers is ingress policy machinery, not generic gateway ownership. Focused parser tests and compilation of all six direct service-policy consumers passed. |
d3cd6d520 |
spinifex/gateway/policy |
spinifex/foundation/aws/policy |
AWS wire-service to IAM action-name mapping is protocol-neutral AWS vocabulary. Its focused suite and direct gateway/RDS/integration caller compilation passed. |
be7f0b1d0 |
spinifex/utils/platform |
spinifex/domains/ec2/platform |
EC2 Platform and UsageOperation derivation is EC2 compatibility vocabulary, not a generic helper. Focused package and metadata-default tests, plus direct daemon/image/instance caller compilation, passed. |
e2ac3dbed |
spinifex/utils/command |
spinifex/runtime/host/command |
Bounded host-command execution is node-local runtime machinery. Focused command and host-DNS tests plus the direct SPX CLI caller compilation passed. |
3360382f5 |
spinifex/utils/idempotency |
spinifex/foundation/lifecycle/idempotency |
Retry-token HTTP/NATS vocabulary now lives beside the idempotency store. Focused propagation and EIP retry behavior tests, affected package compilation and tagged integration compilation passed. |
b5bc8cd7d |
spinifex/utils/images (SelectNewestImage) |
spinifex/foundation/aws/ami |
Selecting the newest EC2 image from AWS SDK models is shared AWS-model logic used by EKS, ECS, RDS and Bedrock, not operator catalogue ownership. Focused selector and remaining catalogue tests plus all four direct caller compilations passed. |
9f83f899a |
spinifex/utils (ClientIP, RequestClientIP) |
spinifex/ingress/http |
HTTP remote-address parsing and loopback-trusted X-Real-IP handling are generic ingress policy shared by the AWS gateway and UI proxy. The moved test suite and all direct caller compilations passed. |
693109950 |
spinifex/utils (HashMAC) |
spinifex/network/identifiers |
Deterministic locally-administered MAC derivation is network infrastructure shared by ENIs, DHCP, OVN topology, IMDS and VM tap setup. Focused MAC tests and every direct caller compilation passed. |
79cf93996 |
spinifex/utils (DistinctIDs) |
spinifex/foundation/aws/identifiers |
Request-order-preserving normalization of AWS resource-ID lists is shared API-model handling used by image and snapshot enumeration. Focused tests and both direct caller compilations passed. |
7e29f2640 |
spinifex/utils (download and terminal-progress helpers) |
spinifex/operator/progress |
Operator-facing downloads, terminal progress rendering and byte display are CLI presentation concerns. Focused tests and the spx admin compilation passed. |
56471479f |
spinifex/utils (ValidateKeyPairName) |
spinifex/handlers/ec2/key |
EC2 key-pair-name validation has one production owner and is now private to it. Its moved unit matrix and full key-handler suite passed. |
cf531cd73 |
spinifex/utils (QMP telemetry filename convention) |
contracts/telemetry/v1 |
The telemetry QMP prefix and metadata path are part of the existing VM-runtime-to-collector file contract. The contract test, focused VM telemetry tests, collector suite and caller compilations passed; the broader VM suite is sandbox-blocked by unrelated socket setup. |
83615f1f4 |
spinifex/utils (AWS XML response helpers) |
spinifex/foundation/aws/xml |
EC2 XML response normalization/enveloping and IAM-style Query envelopes are shared AWS protocol mechanics. Focused XML tests and all direct caller compilations passed; the RDS-agent package was compile-checked without execution because its FIPS bootstrap requires a FIPS-enabled runtime. |
9896834b2 |
spinifex/utils (ExtractTags, MapToEC2Tags) |
spinifex/foundation/aws/tags |
Generic EC2 tag-specification extraction and API-model projection join the AWS tag foundation; KV tag mirroring remains separate state-layer work. Focused tag tests and direct caller compilations passed; the volume package was compile-checked without execution because its test main opens a sandbox-blocked TCP listener. |
d8985c287 |
spinifex/utils (AccountKey) |
spinifex/foundation/state/kvutil |
Account-scoped durable-key construction belongs to the state foundation; its {accountID}.{resourceID} layout is unchanged. AWS account policy (GlobalAccountID, IsAccountID) remains separate legacy utility work. Focused key and tag-mirror tests plus every direct resource-caller compilation passed. |
e6794d87d |
spinifex/utils (SudoCommand, NeedsPrivilege, EndpointSysctlHelper) |
spinifex/runtime/host/command |
Host-command privilege escalation is node-local runtime machinery and now sits beside bounded command execution. The RG-10 invariant restricting direct sudo construction to this package and network/host/run.go moves with it. Focused privilege, preflight, network-host, host-DNS and vpcd tests, every direct caller compilation and tagged integration/E2E compilation passed. |
fd6c12f14 |
spinifex/utils (PID files, runtime directory, socket waits, process signalling and OOM score) |
spinifex/runtime/host/process |
Node-local process supervision shared by the daemon, VM runtime, Viperblockd and every named role is runtime host machinery. The remaining NBD endpoint helpers temporarily import it until they move to compute runtime. The shipped Viperblock unit comment still names utils.KillProcess; it is left unchanged so a structural move does not alter a delivered unit. Full preflight (excluding the pre-existing containerd advisory), focused caller suites and tagged integration/E2E compilation passed. |
e712c6a7f |
spinifex/utils (NBD socket paths, URI format/parse, readiness wait) |
spinifex/runtime/compute/nbd |
NBD endpoint naming and readiness join the node-local NBD runtime, removing the interim utils to runtime-host edge. The EBS provider conformance suite now imports compute runtime for the URI format; if a versioned EBS wire contract is introduced, that format is a candidate for contracts/ebs/v1. Full preflight (excluding the pre-existing containerd advisory), focused NBD, VM, Viperblockd, QEMU-NBD, EBS-provider and admin suites, and tagged integration/E2E compilation passed. |
366e2c2e4 |
spinifex/utils (image catalogue, checksum verification, disk-image extraction) |
spinifex/operator/imagecatalog |
The published image catalogue and its download verification serve only spx admin image import, an operator use case. The package is named imagecatalog because the command tree already uses images as a local identifier. Moved tests reach repository fixtures one directory deeper; script and documentation pointers to the catalogue file were updated. Full preflight (excluding the pre-existing containerd advisory), focused catalogue and CLI suites, and tagged integration/E2E (including GPU) compilation passed. |
53f13f213 |
spinifex/utils (GenerateResourceID) |
spinifex/foundation/aws/identifiers |
AWS-style {prefix}-{17 hex} resource-ID generation joins the AWS identifier foundation beside request-ID normalisation; callers use the established awsidentifiers alias, which also avoids the network-identifier package name. Format and CSPRNG failure handling are unchanged. Full preflight (excluding the pre-existing containerd advisory), focused tests and tagged integration/E2E compilation passed. |
eab631b42 |
spinifex/services/predastore |
spinifex/runtime/roles/predastore |
Predastore process configuration and startup are a named runtime role; the package holds no S3 resource semantics. The service manifest path moved with it. Full preflight (excluding the pre-existing containerd advisory), focused role, role-catalogue and CLI suites, and tagged integration/E2E compilation passed. Commit 796fb52d4 separately corrects the manifest's stale handlers/acm path left by the ACM relocation; manifest-check now passes. |
ad6a158f8 |
spinifex/services/northstar |
spinifex/runtime/roles/northstar |
Northstar process startup and reload are a named runtime role. BootstrapBaseZone moved with it unchanged but is DNS control-plane work (it imports handlers/dns); it belongs to domains/dns when that domain moves, so the role is not yet thin. Full preflight (excluding the pre-existing containerd advisory), focused role, role-catalogue and CLI suites, manifest-check and tagged integration/E2E compilation passed. |
931d86d5c |
spinifex/services/awsgw |
spinifex/runtime/roles/awsgw |
The AWS gateway process is a named runtime role and its composition root wires every domain, which runtime may do. The quota reconcile loop (runQuotaReconcile, quotaKeyFor) moved with it unchanged but belongs to domains/admission/quota, and the EKS token-verify responder belongs with STS or EKS identity; both are recorded residuals, so the role is not yet thin. Service-interface manifest, design doc and architecture diagram paths were updated. Full preflight (excluding the pre-existing containerd advisory), focused role, role-catalogue and CLI suites, manifest-check and tagged integration/E2E compilation passed. |
745338563 |
spinifex/utils (GenerateErrorPayload, GenerateErrorPayloadWithMessage, ValidateErrorPayload, UnmarshalJsonPayload) |
spinifex/foundation/aws/errors |
The JSON error envelope every domain exchanges over NATS carries the shared AWS error vocabulary, so it sits beside the codes it encodes rather than in a per-domain contract. Behaviour is unchanged. Full preflight (excluding the pre-existing containerd advisory), focused error and caller suites and tagged integration/E2E compilation passed. |
02e0dd0dc |
spinifex/utils (GlobalAccountID, IsAccountID) |
spinifex/foundation/aws/identifiers |
The 12-digit account ID check and the system account ID constant are AWS identifier vocabulary and sit beside resource ID generation; no account policy changed. Full preflight (excluding the pre-existing containerd advisory), focused identifier and caller suites and tagged integration/E2E compilation passed. |
b5806ce63 |
spinifex/utils (NATS connect/retry, request/serve, gather, headers, PublishEvent, trace propagation) |
spinifex/foundation/messaging/nats (package natsmsg) |
Generic NATS transport primitives are shared machinery with no resource owner; the package name avoids colliding with nats.go at every caller. The OTel instrumentation scope keeps its spinifex/utils value so existing APM queries still match. vpcd's request/ack protocol (RequestEvent, AddNAT, PublishNATEvent) stays in utils/vpcd_event.go for a future network contract, and SubjectEnsureDefaultVpc stays in utils/ec2_subject.go for an EC2 contract; both were split out byte-identical. Full preflight (excluding the pre-existing containerd advisory), focused transport and caller suites and tagged integration/E2E compilation passed. |
cabe0e99b |
spinifex/handlers/sysinstance |
spinifex/domains/ec2/systeminstance |
System-instance launch is compute ownership; managed services (ELBv2, EKS, RDS, Bedrock) consume the launcher contract. The package was renamed to its directory; runtime sysinstance: error strings are unchanged. Managed-service parent metadata is still only the ManagedBy tag value, short of the explicit parent metadata the ADR names. Full preflight (excluding the pre-existing containerd advisory), focused daemon and managed-service suites and tagged integration/E2E compilation passed. |
4d86296eb |
spinifex/handlers/systemvpc |
spinifex/domains/network/systemvpc |
Managed system-VPC realisation is network ownership; ELBv2, EKS, RDS and Bedrock consume its builder. The package was renamed from handlers_systemvpc to its directory and callers dropped the alias; it depends only on foundation packages. Full preflight (excluding the pre-existing containerd advisory), focused system-VPC, daemon and managed-service suites and tagged integration/E2E compilation passed. |
09de514ef |
spinifex/handlers/imds |
spinifex/domains/ec2/guestmetadata |
Guest metadata is a compute-domain interface served to guests on each node. The package was renamed from handlers_imds to its directory and its vpcd and E2E callers dropped the alias; five path comments were updated. The move exposes dependency-rule breaks it does not repair: imports of the DNS, EC2 instance, EC2 key, IAM and STS implementations, and the first domain-to-runtime edge (runtime/compute/vm); see Guest metadata relocation residuals. Full preflight (excluding the pre-existing containerd advisory), focused guest-metadata, vpcd and DNS suites and tagged integration/E2E compilation passed. |
99278d5ff |
spinifex/handlers/dns |
spinifex/domains/dns |
DNS control semantics (zone records, resolver and name policy) are DNS-domain ownership, distinct from OVN and host-network realisation. The package name was already dns, so callers dropped the handlers_dns alias; the multinode E2E test that also imports miekg/dns uses dnsdomain. Six path comments were updated. The move exposes imports of runtime/compute/vm, network/reconcile and bootstrap/config, recorded in the dependency-rule debt. The integration,segscanoracle build fails identically on origin/dev (predastoreS3Client is in package integration but called from integration_test) and was not touched. Full preflight (excluding the pre-existing containerd advisory), focused DNS, ACM, guest-metadata, daemon, northstar, admin and CLI suites, manifest-check and tagged integration, E2E and E2E bench compilation passed. |
06b1eefd9 |
spinifex/runtime/roles/northstar (BootstrapBaseZone) |
spinifex/domains/dns |
Seeding the base zone and its NS topology is DNS control-plane work, so it joins the DNS domain and the northstar role is left with process startup and reload only. Its tests moved with it and reuse the DNS package's identical fakeS3 helper. The daemon flakes seen during verification (TestRestoreInstances_ClusterRecordWinsForSharedInstance under load; TestKVIPSecBarrier_* and TestDrainVolumeRecordsItsPointAfterTheWork under -count=3) reproduce identically on origin/dev. Full preflight (excluding the pre-existing containerd advisory), focused DNS, northstar and CLI suites and tagged integration/E2E compilation passed. |
8ca318070 |
spinifex/admin (SystemAccountID) |
spinifex/foundation/aws/identifiers (GlobalAccountID) |
SystemAccountID() duplicated the existing GlobalAccountID constant (000000000000), so its callers now use the constant and the function and its test are deleted rather than moved. DefaultAccountID and DefaultAccountName are Mulga bootstrap identity policy, not AWS identifier syntax, and stay in admin for a later IAM/account bootstrap slice. Full preflight (excluding the pre-existing containerd advisory), focused admin, account-teardown, EKS, CLI and identifier suites and tagged integration/E2E compilation passed. |
930040875 |
spinifex/admin (LoadCAKeyPair) |
spinifex/foundation/pki |
Loading a PEM certificate and PKCS8 RSA key is a generic primitive; the new package imports no Spinifex package and holds no certificate identity or file layout. GenerateCACert and GenerateSignedCert stay in admin because they embed Spinifex certificate identity and validity policy. Full preflight (excluding the pre-existing containerd advisory), focused admin and RDS suites and tagged integration/E2E compilation passed. |
001aa2d42 |
spinifex/admin (TenantCACertPath, TenantCAKeyPath) |
spinifex/domains/acm |
The tenant private CA's on-disk layout belongs to ACM, beside LoadTenantCA and LoadOrCreateTenantCA, which consume it; the daemon and the spx admin acm command now call the ACM domain. Full preflight (excluding the pre-existing containerd advisory), focused ACM, admin, daemon and CLI suites and tagged integration/E2E compilation passed. |
454defb00 |
spinifex/admin (IPsec certificate paths, peer issuance, strongSwan CA install and reread) |
spinifex/network/host |
IPsec peer credentials belong with the host IPsec owner that consumes them; network/host no longer imports admin. Peer keys use their own ipsecCertKeyBits seam (4096, lowered in tests) instead of admin's certKeyBits, a deliberate duplicate of the key-size policy. The moved test now builds its throwaway CA locally instead of calling admin's GenerateCACert. Full preflight (excluding the pre-existing containerd advisory), the four moved tests, focused network-host, admin and CLI suites and tagged integration/E2E compilation passed. |
2c467988d |
spinifex/handlers/bedrock |
spinifex/domains/ochre |
Ochre is the platform service and owns model serving placement, launch, readiness, capacity and reaping; the Bedrock name now marks only the AWS API surface, per the amended ADR-0001 map row. Package renamed from handlers_bedrock to ochre, callers drop the alias, and KV bucket names, NATS subjects, metric names and error strings keep their bedrock names. The comment in the shipped bedrock-serve image script still names the old path because editing it changes image build input. Full preflight apart from the known govulncheck finding, focused Ochre, vector, Bedrock gateway, daemon, account teardown, awsgw, config and CLI tests, and tagged integration/E2E compilation passed. |
The EC2 contract row is intentionally different from the directory moves: it creates
a compatibility boundary. ec2.cmd.* retains its deployed one-token NATS
subscription and permission shape, while callers use
InstanceCommandSubject rather than reconstructing the subject. The
contract's README states the route, scope and change rule.
ECR composition boundary remaining
The ECR AWS JSON dispatcher and /v2/* route assembly remain methods on the
generic GatewayConfig. They establish the generic HTTP route, authenticated
request context, bounded-body read and policy gate, then invoke the ECR domain
packages above. They are not moved merely to remove the last ECR-named files
from gateway: doing so first would make the ECR domain own generic gateway
state and policy mechanics.
Registry-backed image actions have now crossed this boundary through
awsapi.RegistryActionService: the composition root supplies the OCI
capabilities, and the generic gateway dispatches through it after authorization.
Lifecycle-preview actions have likewise crossed it through
awsapi.LifecyclePreviewActionService, whose policy-store-plus-image-catalog
dependencies remain explicit and separate from the registry image-action
service.
Repository metadata actions have crossed it through
awsapi.RepositoryActionService, which makes both their narrow metadata-store
dependency and advertised endpoint profile composition explicit.
Authorization-token issuance has crossed it through
awsapi.AuthorizationTokenActionService. Gateway intentionally still builds
the canonical IAM/STS principal before dispatch, because ECR must not depend on
gateway identity context or ARN construction.
All implemented ECR control-plane actions now dispatch through explicit ECR
capabilities. The remaining ECR-named gateway code is generic /v2/* route
assembly, SigV4/registry authentication and policy enforcement; it remains in
gateway rather than inverting those dependencies into the ECR domain.
ACM relocation residuals
The ACM move leaves two pre-existing dependency seams visible rather than changing their behaviour in a structural slice:
domains/acm.Storestill imports IAM's AES-GCM helper functions. It does not read IAM records, but the crypto mechanism must move behind a shared crypto boundary before the final domain-dependency lint can prohibit that implementation import.GatewayConfigstill owns the ACM action-name dispatch map. ACM owns the action adapters and resource-scope derivation, while generic gateway owns route handling, request context, policy gating and response writing. Moving service registration itself needs the later ingress registration contract; it is not hidden by a compatibility shim in this move.
Guest metadata relocation residuals
The guest-metadata move keeps every existing import unchanged, so the domain package now shows these breaks of the target dependency rules. Each needs a consumer-owned capability, projection or versioned contract before the dependency lint (ADR step 8) can be enabled.
domains/ec2/guestmetadataimports the DNS, EC2 instance, EC2 key, IAM and STS implementations, which breaks rule 3 (no domain reads another domain's implementation).domains/ec2/guestmetadataimportsruntime/compute/vmfor instance records and VM reconstruction, the first domain-to-runtime edge; runtime is meant to compose domains, not be imported by them.
Dependency-rule debt to clear after the moves
These residuals were recorded by individual slices and must be resolved once the structural moves are complete, before the dependency lint is enabled.
- Guest metadata: the cross-domain and runtime imports above.
admin→operator/adminis blocked until its shared pieces have owners:DefaultAccountID/DefaultAccountName(IAM/account bootstrap),GenerateAWSAccessKey/GenerateAWSSecretKey(IAM credentials),PromoteSystemImage(EC2 image domain), andGenerateCACert/GenerateSignedCert(Spinifex certificate issuance, used by the NATS role and RDS).domains/dns: importsruntime/compute/vm(domain-to-runtime),network/reconcilefor the reconcile lock andbootstrap/configfor node configuration.- ACM: the IAM AES-GCM helper import and gateway-owned action dispatch (ACM relocation residuals).
runtime/roles/awsgw: the quota reconcile loop belongs todomains/admission/quota, and the EKS token-verify responder belongs with STS or EKS identity.utils:vpcd_event.go(vpcd request/ack protocol and NAT helpers) awaits a network contract,ec2_subject.goawaits an EC2 contract, andencryption.goandtagmirror.goawait the EC2/EBS slices.runtime/compute/cache.New: two construction-time panics carry a lint exemption pending a constructor that returns an error.domains/ec2/systeminstance: managed-service parent metadata is only theManagedBytag value.
Recording rule
For every later slice, add the old and new path, source commit, focused verification, and any finding exposed by the move. Record a conflict rather than folding a behavioural repair into a structural commit. When this branch is merged, the umbrella repository's execution plan records the resulting Spinifex commit.