Documentation
¶
Overview ¶
Package admin runs the second HTTP server fronting the rule-mutation API. It's a sibling to the user-facing web/tcp/cron personalities: separate port, separate auth, but shares the same processor + db.
Wire from chassis/server/server.go when "admin" is in --personalities.
Index ¶
- type Controller
- func (c *Controller) ApplyStackVersion(ctx context.Context, tx *sql.Tx, tenantID, stack string, version int64, ...) error
- func (c *Controller) BackfillStructuredHostDKIM(ctx context.Context) (int, error)
- func (c *Controller) EnableRoomRelay(name string) error
- func (c *Controller) EnsureStructuredSuffixZone(ctx context.Context) error
- func (c *Controller) PublishSecretRevoke(ctx context.Context, tenantID string, parentRow map[string]any) (func(*sql.Tx) error, error)
- func (c *Controller) PublishSecretUpsert(ctx context.Context, tenantID string, versionRow, parentRow map[string]any) (func(*sql.Tx) error, error)
- func (c *Controller) ReconcileStorePacks(ctx context.Context, tenantID, stack string, version, priorVersion int64, ...)
- func (c *Controller) SetArtifactStore(s artifact.Store)
- func (c *Controller) SetFileCAS(s filecas.Store)
- func (c *Controller) SetGate(ctx context.Context, slug string, suspended bool, denyStatus int, ...) error
- func (c *Controller) SetStoreReconciler(r *storeseed.Reconciler)
- func (c *Controller) SetVectorStore(v vector.Store)
- func (c *Controller) Start()
- func (c *Controller) Stop()
- type OpRecord
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
func NewController ¶
func NewController(ctx context.Context, pu *processor.Unit) *Controller
func (*Controller) ApplyStackVersion ¶
func (c *Controller) ApplyStackVersion(ctx context.Context, tx *sql.Tx, tenantID, stack string, version int64, now string) error
ApplyStackVersion is the non-HTTP entry point to the activation core, used by the control-event applier (chassis/controlapply) to materialise a stack.activated event. It runs the same transactional logic the admin handler uses; the caller owns tx begin/commit and any dbcache reload. The HTTP-only status/code/detail is collapsed to a plain error.
func (*Controller) BackfillStructuredHostDKIM ¶ added in v0.2.6
func (c *Controller) BackfillStructuredHostDKIM(ctx context.Context) (int, error)
BackfillStructuredHostDKIM mints a per-host DKIM keypair for every active chassis-minted structured host that predates the per-host key columns (0017) — created_by = structured-host with an empty key. Idempotent: hosts that already have a key are skipped, so re-running (e.g. every boot) is a cheap no-op once the fleet is keyed. Each updated row is fleet-published so data- plane nodes sign with it and the dns head publishes its per-host records. Control-plane only. Returns the number of hosts newly keyed.
func (*Controller) EnableRoomRelay ¶ added in v0.2.10
func (c *Controller) EnableRoomRelay(name string) error
EnableRoomRelay opens the named cross-node room relay and attaches it to the hub so room messages fan out across fleet nodes (the relay's inbound feed is wired to hub.Deliver). Empty name is a no-op (rooms stay in-process). Called from boot when --room-relay is set; the relay is closed in Stop.
func (*Controller) EnsureStructuredSuffixZone ¶ added in v0.2.6
func (c *Controller) EnsureStructuredSuffixZone(ctx context.Context) error
EnsureStructuredSuffixZone idempotently creates the system-owned zone for the configured structured-host suffix (e.g. stacks.thanks.computer), making the chassis authoritative for it: synth emits a WILDCARD A/MX/SPF when a zone's origin == the suffix, and per-host DKIM/DMARC come from the structured-host rows. Reuses the zone create + fleet-publish + dbcache-reload path. Control-plane only (the caller gates on the 'admin' personality + --structured-dns-self). No-op when the zone already exists.
func (*Controller) PublishSecretRevoke ¶ added in v0.2.16
func (c *Controller) PublishSecretRevoke( ctx context.Context, tenantID string, parentRow map[string]any, ) (func(*sql.Tx) error, error)
PublishSecretRevoke implements secrets.Syncer for a revoke: one tenant_secrets upsert carrying revoked_at (the consumer's INSERT OR REPLACE flips it inactive), as a TypeSecretRevoked event.
func (*Controller) PublishSecretUpsert ¶ added in v0.2.16
func (c *Controller) PublishSecretUpsert( ctx context.Context, tenantID string, versionRow, parentRow map[string]any, ) (func(*sql.Tx) error, error)
PublishSecretUpsert implements secrets.Syncer for create / rotate / description changes. versionRow is nil for a parent-only change. The version event is queued BEFORE the parent so a consumer never briefly sees a tenant_secrets row pointing at an absent version.
func (*Controller) ReconcileStorePacks ¶ added in v0.2.16
func (c *Controller) ReconcileStorePacks(ctx context.Context, tenantID, stack string, version, priorVersion int64, origin bool)
ReconcileStorePacks loads the version's CHANGED VECTORS/ + KV/ packs and reconciles them into the runtime stores. It is invoked AFTER the activation tx commits, from both the control-plane admin handler (origin=true) and the data-plane applier (origin=false, in package controlapply — hence exported).
Store key = the tenant SLUG. The runtime keys every store by the slug (processor.TenantScope), but the control plane only has the tenant_id in hand; keying the reconcile by the id would seed under a different identifier than the runtime reads (collection-not-found at search time). storeTenantKey resolves it. stack_files queries below stay on tenant_id — that's the durable DB FK.
Change-driven, self-healing: a pack is reconciled when its content-hash differs from the prior active version (priorVersion) OR when its target is absent from the store. A code-only deploy (`txco apply`) carries packs forward unchanged and the targets already exist → empty set → no item reconcile (just a cheap presence probe per vector pack). priorVersion <= 0, or any diff failure, reconciles every pack (correct for a first activation / a fresh or wiped node).
Best-effort by contract: it logs and swallows every error so a slow or failing store never stalls or rolls back a deploy — the pack bytes are durable in the CAS, so a missed reconcile is retried on the next apply/reload.
func (*Controller) SetArtifactStore ¶
func (c *Controller) SetArtifactStore(s artifact.Store)
SetArtifactStore wires the artifact store the admin handlers use to publish event payloads when fleet-sync producer is enabled. The chassis boot calls this after opening the artifact store; handlers guard internally on FeedSink != nop before touching it.
This is also where the Controller registers itself as the secret store's fleet Syncer (so create/rotate/revoke fan out): it's the "this node is a producer" hook. The PublishSecret* methods self-gate on fleetEnabled(), so registering here is safe even on a single-node chassis (they no-op). nil Secrets (feature off) ⇒ nothing to wire.
func (*Controller) SetFileCAS ¶ added in v0.2.6
func (c *Controller) SetFileCAS(s filecas.Store)
SetFileCAS wires the content-addressed store activation uses to persist tenant FILES/ asset bytes. Nil-safe.
func (*Controller) SetGate ¶ added in v0.2.6
func (c *Controller) SetGate(ctx context.Context, slug string, suspended bool, denyStatus int, denyReason string) error
SetGate engages or releases the programmatic admission gate for a tenant, identified by slug — the identity background services see in usage data (the envelope `_txc.tenant`). It owns the `suspended` column exclusively (operator disable owns `enabled`) and routes through applyRuntimeRow so the full-row write + fleet emit + dbcache reload is reused, never a partial row. Unknown or revoked slugs are a no-op (the caller logs). This makes *Controller satisfy bgservice.Gate, which is injected into background services at boot.
func (*Controller) SetStoreReconciler ¶ added in v0.2.16
func (c *Controller) SetStoreReconciler(r *storeseed.Reconciler)
SetStoreReconciler wires the declarative store-seed reconciler the activation path runs (post-commit, best-effort) to materialise VECTORS/ + KV/ packs into the runtime stores. Nil-safe: unset ⇒ packs are inert.
func (*Controller) SetVectorStore ¶ added in v0.2.16
func (c *Controller) SetVectorStore(v vector.Store)
SetVectorStore wires the vector store the inspect/teardown admin endpoints read (`txco vector ls/show/diff/rm`). Nil-safe.
func (*Controller) Start ¶
func (c *Controller) Start()
func (*Controller) Stop ¶
func (c *Controller) Stop()
type OpRecord ¶
type OpRecord struct {
Stack string `json:"stack"`
Scope int `json:"scope"`
Name string `json:"name"`
Txcl string `json:"txcl"`
MockReq string `json:"mock_req,omitempty"`
MockRes string `json:"mock_res,omitempty"`
}
OpRecord is the wire shape for a single rule in the admin API. It maps 1:1 to a row in the `ops` table.
Identity is `(stack, scope, name)` — the name comes from the rule's filename minus the `.txcl` extension on the developer's disk. Multiple rules per (stack, scope) are first-class: each name is one row, and each runs in parallel at that stage.
Source Files
¶
- auth_endpoints.go
- browserauth.go
- cli_exec.go
- computes.go
- control_publish.go
- cron_config_endpoints.go
- demo.go
- dns_config_endpoints.go
- dns_crud_endpoints.go
- dns_fleet.go
- dns_render.go
- error_logging.go
- fleet_resync.go
- gate.go
- invite_endpoints.go
- legacy_routes.go
- oauth_endpoints.go
- oauth_verify.go
- ops.go
- room_endpoints.go
- secret_endpoints.go
- secret_fleet.go
- server.go
- stacks.go
- storeseed.go
- tenant_endpoints.go
- tenant_hostname_endpoints.go
- tenant_middleware.go
- tenant_runtime_endpoints.go
- throttle.go
- tls_ask.go
- trace_request.go
- trace_stream.go
- traces.go
- vector_inspect.go