# nexuscrm-controlplane
> Lifecycle orchestration for NexusCRM pack install, upgrade, migration, verify, and drift.

Part of the **NexusCRM platform**, split by release boundary into L0 platform repos + L1 product packs + L2 tenant delivery. This repository is an **L0 platform lifecycle module**.

## What this is
This is the lifecycle concern of the platform — host-agnostic and backend-free. It owns pack install, upgrade, migration, apply, verify, and drift detection; component ownership and hashing; dependency ordering; and runtime-profile registration. It also includes `bootstrapimpl`, the single source for schema provisioning, field-provenance initialization, and autonumber seeding. It is the orchestration layer that takes packs and brings a database to a correct, verified L0 state.

## Role in the L0 / L1 / L2 architecture
This is an L0 concern module: platform **mechanism** for getting metadata and packs applied and kept consistent, not product behavior or tenant boot. It depends on the contract and the core engine modules but is deliberately host-agnostic — **it must never import `backend`**. Backend and tenant distributions drive it; it does not drive them.

## What belongs here
- Pack install / upgrade / migration / apply / verify / drift
- Component ownership and hashing
- Dependency ordering across packs and components
- Runtime-profile registration
- Schema provisioning, field-provenance init, and autonumber seeding (`bootstrapimpl`)

## What does NOT belong here
- Backend server runtime or HTTP host wiring
- Tenant deploy shape
- Salesforce route projection or product business behavior
- **Any import of `backend`**

## Public surface (key packages)
- `controlplane` (root) — lifecycle entrypoints: `ApplyMetadata`, `ApplyPacks`, `Verify`/`VerifyDeep`, `RunRepair`, `EnsureL0SchemaDDL`, `NewRunner`, and the operations/verify graph
- `bootstrapimpl` — single source for schema provisioning, field-provenance init, autonumber seeding
- `catalogtenant` — durable tenant namespace, exact OrgID binding, and tenant-owned layout-bundle slot command authority
- `packs`, `packspec`, `specdrift` — pack application, spec definition, and drift detection
- `platform` — platform-level lifecycle wiring
- `tenantoverlay` — tenant overlay application
- `layoutownership` — component/layout ownership tracking

## Dependency rules
- May depend on: `nexuscrm-contract`, the core engine modules (pinned to NexusCRM remote submodule versions), and `nexuscrm-connectors` `v0.1.0`
- Must NOT depend on: `backend`

## How it is consumed
```go
require github.com/pingcap-inc/nexuscrm-controlplane v0.1.1
```
Consumed by the backend and distributions to install, verify, and reconcile pack lifecycle.

## Release & versioning
Published private module, semver tags (`v0.1.1`). Breaking changes are rare and bump minor/major; consumers pin a version.

### Catalog reconcile image publisher

The repository owns the Catalog reconcile image publisher. The thin `main`
caller invokes the reusable authority workflow at immutable foundation commit
`4c215f761786f4ae66a8a2a4b834c30e601abfd4`. AWS OIDC trust requires that same
`job_workflow_ref`; a branch reference cannot exercise the signing role.

Three repository-scoped, read-only deploy keys fetch the exact `NexusCRM`,
`nexuscrm-connectors`, and `nexuscrm-contract` module graph. Only the isolated
signer job receives OIDC/KMS authority. The canonical verifier inputs are
`release/catalog-reconcile-image-signing-policy.json` and the public key it
names. L2 consumes those facts but has no Catalog signing permission.

The release state machine is fixed: pending candidate -> owner signature ->
independent verification -> immutable source-SHA tag. An existing source-SHA
tag is verification-only and is never rebuilt, re-signed, or overwritten. L2
may verify and pin the resulting digest but cannot sign this repository's
artifact.


### Connector projection range cutover

`cmd/connector-projection-cutover` records one immutable boundary per connector
incarnation after old projection work has drained. It requires
`CONNECTOR_CUTOVER_DSN` and `-pack-install-id`; `-timeout` defaults to five minutes.
It audits retained execution owners and refuses live or unresolved projection
work. It never changes historical Event/WorkItem rows, backfills input ranges,
retires backlog, or changes execution status to pass a gate.

L2 must first apply the additive canonical Core schema, fence new admission,
keep old workers running until their durable projection queue is terminal, and
then stop every old writer/worker before invoking the cutover. A lease-only
wait or worker shutdown is not a durable queue drain. Empty-incarnation
initialization is part of pack activation. After the checkpoint, new runtime
inputs have native ranges; old duplicate receipts do not recreate missing
historical work. This narrows the previous speculative source-projection repair
behavior; ordinary per-Event task repair is unchanged.

The release gate checks for unowned live history before selecting installation
incarnations; deleted routes alone do not require a cutover. If the earlier
WorkItem handoff receipt is missing, its existing locked authority proof can
stamp it without retiring any history. Missing source identity cannot merge
unresolved inputs behind another source's terminal task. Both initial activation
and source-revision activation initialize the new incarnation's protocol in the
same transaction; retained old checkpoints remain unchanged.

Every source-revision entrypoint also checks the old incarnation inside the
shared, pack-locked Begin transaction. If it retains Event/WorkItem history but
has no valid checkpoint, the transition stops before changing its identity;
the operator must perform the existing fenced cutover first. Empty failed
attempts can retry without manufacturing historical receipts. The audit uses
the existing WorkItem execution-authority rule and rejects ambiguous duplicate
owners; a terminal compatibility mirror alone is not proof of completion.
After a revision, retained inputs remain accounted for by the old immutable
cutoff or a terminal native range with matching identity and bounds. Live
orphan WorkItems remain an error.

The no-backfill promise above belongs to this checkpoint operation. The wider
ApplyAll workflow still contains the pre-existing source-lane backfill for
Events missing indexed source fields; an older database may need that separate
upgrade step. This PR does not change or execute that migration.

The coordinated protocol and operational limits are documented in Connectors'
`docs/source-projection-input-ranges.md`. Local/CI walking proof is Core's
`tests/integration/connector-projection-ranges.sh`; final rollout remains owned
by the target L2 delivery repository.

### Navigation input preflight

`catalog-reconcile application-navigation -input input.json -validate-only`
uses the same decoder and semantic validation as initialization, then exits
without opening a database or writing an output receipt. Installers must run
this before changing shell metadata in a shared database. It cannot be combined
with `-assert-only`, which verifies persisted navigation and requires a database.
Successful preflight validates input only; it does not guarantee later database
initialization will succeed.

### Composite handlers and workload admission

Catalog reconcile v4 accepts `handlerWorkloadCapabilities` when a selected
handler also calls workload-admitted Runtime RPCs. The deployment derives this
sorted list from the grants for its handler workload. It must be required by
the verified AppRelease and disjoint from concrete Catalog serving selections
and disclosure capabilities. When supplied, it closes all handler workload
dependencies. Older v4 inputs with entirely omitted workload handlers retain
their existing representation.

The reconcile config owns validation of concrete Runtime selections. Durable
handler authority owns the exact partition of selected and workload-admitted
App handlers, their verified dependency lists, and authorized workloads. A
selected composite handler's full dependency list is not a list of Catalog
serving selections; those dependency sets may overlap. Navigation uses current
Runtime configuration and has no Catalog serving projection.
