@msn-control/liftoff 0.9.9 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEVELOPER.md +142 -0
- package/README.md +26 -18
- package/assets/governance/single-maintainer-gitflow/policy.md +13 -11
- package/dist/args.js +21 -0
- package/dist/args.js.map +1 -1
- package/dist/artifact-lifecycle.d.ts +1 -1
- package/dist/artifact-lifecycle.js +5 -0
- package/dist/artifact-lifecycle.js.map +1 -1
- package/dist/commands.js +355 -13
- package/dist/commands.js.map +1 -1
- package/dist/file-system.js +100 -13
- package/dist/file-system.js.map +1 -1
- package/dist/governance-activation/activation-state.d.ts +32 -0
- package/dist/governance-activation/activation-state.js +165 -0
- package/dist/governance-activation/activation-state.js.map +1 -0
- package/dist/governance-activation/approvals.d.ts +188 -0
- package/dist/governance-activation/approvals.js +508 -0
- package/dist/governance-activation/approvals.js.map +1 -0
- package/dist/governance-activation/canonical-json.d.ts +3 -0
- package/dist/governance-activation/canonical-json.js +36 -0
- package/dist/governance-activation/canonical-json.js.map +1 -0
- package/dist/governance-activation/commands.d.ts +10 -0
- package/dist/governance-activation/commands.js +1023 -0
- package/dist/governance-activation/commands.js.map +1 -0
- package/dist/governance-activation/compatibility.d.ts +68 -0
- package/dist/governance-activation/compatibility.js +447 -0
- package/dist/governance-activation/compatibility.js.map +1 -0
- package/dist/governance-activation/credentials.d.ts +160 -0
- package/dist/governance-activation/credentials.js +403 -0
- package/dist/governance-activation/credentials.js.map +1 -0
- package/dist/governance-activation/doctor.d.ts +10 -0
- package/dist/governance-activation/doctor.js +379 -0
- package/dist/governance-activation/doctor.js.map +1 -0
- package/dist/governance-activation/evidence.d.ts +49 -0
- package/dist/governance-activation/evidence.js +246 -0
- package/dist/governance-activation/evidence.js.map +1 -0
- package/dist/governance-activation/graph.d.ts +397 -0
- package/dist/governance-activation/graph.js +441 -0
- package/dist/governance-activation/graph.js.map +1 -0
- package/dist/governance-activation/identity.d.ts +35 -0
- package/dist/governance-activation/identity.js +89 -0
- package/dist/governance-activation/identity.js.map +1 -0
- package/dist/governance-activation/index.d.ts +18 -0
- package/dist/governance-activation/index.js +19 -0
- package/dist/governance-activation/index.js.map +1 -0
- package/dist/governance-activation/migration.d.ts +44 -0
- package/dist/governance-activation/migration.js +268 -0
- package/dist/governance-activation/migration.js.map +1 -0
- package/dist/governance-activation/readiness.d.ts +23 -0
- package/dist/governance-activation/readiness.js +158 -0
- package/dist/governance-activation/readiness.js.map +1 -0
- package/dist/governance-activation/reconciliation.d.ts +11 -0
- package/dist/governance-activation/reconciliation.js +58 -0
- package/dist/governance-activation/reconciliation.js.map +1 -0
- package/dist/governance-activation/release-integrity.d.ts +11 -0
- package/dist/governance-activation/release-integrity.js +49 -0
- package/dist/governance-activation/release-integrity.js.map +1 -0
- package/dist/governance-activation/seed-lifecycle.d.ts +116 -0
- package/dist/governance-activation/seed-lifecycle.js +609 -0
- package/dist/governance-activation/seed-lifecycle.js.map +1 -0
- package/dist/governance-activation/source-of-truth.d.ts +164 -0
- package/dist/governance-activation/source-of-truth.js +986 -0
- package/dist/governance-activation/source-of-truth.js.map +1 -0
- package/dist/governance-activation/task-projection.d.ts +21 -0
- package/dist/governance-activation/task-projection.js +75 -0
- package/dist/governance-activation/task-projection.js.map +1 -0
- package/dist/governance-activation/transitions.d.ts +163 -0
- package/dist/governance-activation/transitions.js +2128 -0
- package/dist/governance-activation/transitions.js.map +1 -0
- package/dist/governance-activation/type-contract.d.ts +1 -0
- package/dist/governance-activation/type-contract.js +27 -0
- package/dist/governance-activation/type-contract.js.map +1 -0
- package/dist/governance-activation/types.d.ts +390 -0
- package/dist/governance-activation/types.js +108 -0
- package/dist/governance-activation/types.js.map +1 -0
- package/dist/governance-activation/validators.d.ts +17 -0
- package/dist/governance-activation/validators.js +1305 -0
- package/dist/governance-activation/validators.js.map +1 -0
- package/dist/init-filesystem.js +5 -1
- package/dist/init-filesystem.js.map +1 -1
- package/dist/planner.js +3 -3
- package/dist/planner.js.map +1 -1
- package/dist/power-apps-templates.js +14 -1
- package/dist/power-apps-templates.js.map +1 -1
- package/dist/process-runner.d.ts +3 -0
- package/dist/process-runner.js +68 -10
- package/dist/process-runner.js.map +1 -1
- package/dist/repository-governance.d.ts +13 -3
- package/dist/repository-governance.js +357 -51
- package/dist/repository-governance.js.map +1 -1
- package/dist/telemetry/contract.d.ts +1 -1
- package/dist/telemetry/contract.js +6 -0
- package/dist/telemetry/contract.js.map +1 -1
- package/dist/templates.js +320 -25
- package/dist/templates.js.map +1 -1
- package/dist/types.d.ts +14 -6
- package/docs/cli-reference.md +60 -12
- package/docs/configuration-and-manifests.md +40 -16
- package/docs/existing-repositories.md +22 -11
- package/docs/getting-started.md +46 -10
- package/docs/project-structure.md +34 -5
- package/docs/repository-governance.md +200 -245
- package/docs/safety-and-consent.md +24 -2
- package/docs/troubleshooting.md +55 -4
- package/docs/workloads.md +1 -1
- package/package.json +2 -1
package/docs/getting-started.md
CHANGED
|
@@ -38,12 +38,14 @@ a reviewed project change.
|
|
|
38
38
|
|
|
39
39
|
See [prerequisites](prerequisites.md) for the complete plan-derived tool model.
|
|
40
40
|
|
|
41
|
-
## 2. Start
|
|
41
|
+
## 2. Start the primary path
|
|
42
42
|
|
|
43
43
|
From the directory that should contain the project, run:
|
|
44
44
|
|
|
45
|
-
```
|
|
46
|
-
liftoff init
|
|
45
|
+
```text
|
|
46
|
+
liftoff init my-project
|
|
47
|
+
cd my-project
|
|
48
|
+
/liftoff-setup
|
|
47
49
|
```
|
|
48
50
|
|
|
49
51
|
The guided flow asks for:
|
|
@@ -69,8 +71,15 @@ there, validates the complete result, and only then merges it into the target.
|
|
|
69
71
|
OpenSpec projects use all 12 OpenSpec 1.11 workflows as both skills and commands.
|
|
70
72
|
If the global OpenSpec profile differs, Liftoff displays the exact global change
|
|
71
73
|
and asks separately before staging.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
|
|
75
|
+
When governance is enabled, `/liftoff-setup` is the next selected-agent action.
|
|
76
|
+
It has no model-selection requirement: safety comes from the Liftoff CLI phase
|
|
77
|
+
graph, local evidence, approval envelopes, and readback. Setup first completes,
|
|
78
|
+
syncs, and archives the generated `bootstrap-<project>` seed. Only then does it
|
|
79
|
+
reach explicit authority gates for repository commit/push, credentials, billed
|
|
80
|
+
infrastructure or policy exceptions, final enforcement, destructive cleanup, and
|
|
81
|
+
external blockers. Commit and push are never implicit in `liftoff init`, `--yes`,
|
|
82
|
+
or read-only checks.
|
|
74
83
|
|
|
75
84
|
For deterministic generic generation, use `--type genai --pattern generic`.
|
|
76
85
|
|
|
@@ -86,26 +95,53 @@ a project name creates a named child directory.
|
|
|
86
95
|
Read [existing repositories](existing-repositories.md) before initializing a
|
|
87
96
|
non-empty target.
|
|
88
97
|
|
|
89
|
-
## 4.
|
|
98
|
+
## 4. Local baseline setup verifies
|
|
99
|
+
|
|
100
|
+
`/liftoff-setup` runs only local, project-applicable baseline checks before it
|
|
101
|
+
archives the seed:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
liftoff validate
|
|
105
|
+
# backend tests from the generated README when a backend exists
|
|
106
|
+
# frontend build from the generated README when a frontend exists
|
|
107
|
+
docker compose config -q
|
|
108
|
+
tofu fmt -check -recursive
|
|
109
|
+
tofu init -backend=false
|
|
110
|
+
tofu validate
|
|
111
|
+
openspec validate --strict
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Absent components are inapplicable: a Power Apps project does not fabricate
|
|
115
|
+
backend, Docker, or OpenTofu success, and an API project without a frontend skips
|
|
116
|
+
frontend build evidence. The baseline does not run `tofu plan`, `tofu apply`,
|
|
117
|
+
start containers, deploy, mutate GitHub, or require cloud credentials. If a check
|
|
118
|
+
fails, the seed remains active and `/liftoff-setup` resumes idempotently after
|
|
119
|
+
you fix the blocker; verified phases are not repeated.
|
|
90
120
|
|
|
91
|
-
|
|
121
|
+
You can run read-only maintenance at any time:
|
|
92
122
|
|
|
93
123
|
```bash
|
|
94
124
|
liftoff validate
|
|
95
125
|
liftoff doctor
|
|
126
|
+
liftoff governance status --json
|
|
127
|
+
liftoff governance plan --json
|
|
128
|
+
liftoff governance verify --json
|
|
96
129
|
```
|
|
97
130
|
|
|
98
131
|
`validate` checks durable generated artifacts and framework markers. `doctor`
|
|
99
|
-
adds read-only workstation, runtime, authentication, dependency,
|
|
100
|
-
workload-specific diagnostics.
|
|
132
|
+
adds read-only workstation, runtime, authentication, dependency,
|
|
133
|
+
workload-specific, and governance-state diagnostics.
|
|
101
134
|
|
|
102
|
-
|
|
135
|
+
After setup archives the seed and you explicitly approve repository publication,
|
|
136
|
+
normal development follows your selected workflow:
|
|
103
137
|
|
|
104
138
|
- GenAI and API projects: copy `.env.example` to `.env`, install the generated
|
|
105
139
|
stack dependencies, then use `liftoff dev` and `liftoff infra` to print local
|
|
106
140
|
development and infrastructure commands.
|
|
107
141
|
- Power Apps projects: run `npm ci`, then `npm run dev`. Environment binding,
|
|
108
142
|
connector addition, and `power-apps push` are deliberately deferred.
|
|
143
|
+
- OpenSpec or Spec Kit changes drive normal feature work; release and hotfix
|
|
144
|
+
flows follow the governed GitFlow plan after activation evidence is green.
|
|
109
145
|
|
|
110
146
|
See [workloads](workloads.md) for exact generated outputs and deferred actions.
|
|
111
147
|
|
|
@@ -23,7 +23,15 @@ project/
|
|
|
23
23
|
| `-- governance/ # managed-core local handoff when enabled
|
|
24
24
|
| |-- policy.md
|
|
25
25
|
| |-- context.json
|
|
26
|
-
|
|
|
26
|
+
| |-- README.md
|
|
27
|
+
| |-- phase-graph.json
|
|
28
|
+
| |-- compatibility.json
|
|
29
|
+
| `-- credential-policy.schema.json
|
|
30
|
+
|-- governance/ # user-owned activation state after setup starts
|
|
31
|
+
| |-- activation-state.json
|
|
32
|
+
| |-- approvals/
|
|
33
|
+
| |-- evidence/
|
|
34
|
+
| `-- credentials/
|
|
27
35
|
|-- backend/
|
|
28
36
|
| `-- uv.lock # Python stacks only
|
|
29
37
|
|-- database/
|
|
@@ -43,8 +51,10 @@ project/
|
|
|
43
51
|
|-- .claude/skills/openspec-*/ and .claude/commands/opsx/ # OpenSpec + Claude
|
|
44
52
|
|-- .github/workflows/copilot-setup-steps.yml # optional hosted agent
|
|
45
53
|
|-- .github/agents/openspec.agent.md # optional hosted agent
|
|
46
|
-
|-- .github/prompts/liftoff-
|
|
47
|
-
|
|
54
|
+
|-- .github/prompts/liftoff-setup.prompt.md
|
|
55
|
+
|-- .github/prompts/liftoff-repository-governance.prompt.md # compatibility alias
|
|
56
|
+
| or .claude/commands/liftoff-setup.md
|
|
57
|
+
| and .claude/commands/liftoff-repository-governance.md
|
|
48
58
|
|-- frontend/ # only when selected
|
|
49
59
|
|-- functions/<worker-name>/ # only for worker-enabled GenAI patterns
|
|
50
60
|
`-- migration/legacy/ # only after liftoff migrate
|
|
@@ -77,6 +87,10 @@ project/
|
|
|
77
87
|
- OpenSpec projects receive all 12 pinned workflows as both skills and commands
|
|
78
88
|
for supported selected-agent surfaces. The two hosted Copilot agent files are
|
|
79
89
|
generated only after explicit opt-in.
|
|
90
|
+
- `/liftoff-setup` is generated when repository governance is enabled. It calls
|
|
91
|
+
`liftoff governance status|plan|apply-next|resume|verify` and has no model
|
|
92
|
+
selection or separate setup-skill version. `/liftoff-repository-governance` is
|
|
93
|
+
a compatibility alias for the same state.
|
|
80
94
|
|
|
81
95
|
### Conditional areas
|
|
82
96
|
|
|
@@ -111,14 +125,16 @@ project/
|
|
|
111
125
|
| |-- hooks/
|
|
112
126
|
| |-- pages/
|
|
113
127
|
| `-- providers/
|
|
128
|
+
|-- .liftoff/governance/ # managed-core setup files when enabled
|
|
129
|
+
|-- governance/ # user-owned activation state after setup starts
|
|
114
130
|
`-- openspec/ or .specify/
|
|
115
131
|
```
|
|
116
132
|
|
|
117
133
|
The exact selected-agent governance launcher is generated only when the
|
|
118
134
|
repository-governance profile is enabled. It is Liftoff-owned; neighboring
|
|
119
135
|
framework files remain framework-owned. Agent-created governance changes and
|
|
120
|
-
`governance/activation-
|
|
121
|
-
|
|
136
|
+
`governance/activation-state.json`, approvals, evidence, credentials, and
|
|
137
|
+
supersession records remain user-owned and are not listed as managed artifacts.
|
|
122
138
|
|
|
123
139
|
This root follows the pinned official Microsoft starter. It includes the
|
|
124
140
|
Power Apps SDK, Vite plugin, and project-local CLI through locked npm
|
|
@@ -128,6 +144,19 @@ Liftoff intentionally does not generate `backend/`, `database/`,
|
|
|
128
144
|
`docker-compose.yml`, `environments/`, `infrastructure/`, or
|
|
129
145
|
`power.config.json` for this workload.
|
|
130
146
|
|
|
147
|
+
## Managed versus user-owned governance artifacts
|
|
148
|
+
|
|
149
|
+
`liftoff.manifest.json` v7 records managed-core hashes for the governance policy,
|
|
150
|
+
context, guide, phase graph, compatibility metadata, credential-policy schema,
|
|
151
|
+
setup integrations, and compatibility aliases. `liftoff update` may reconcile
|
|
152
|
+
only those managed-core paths. It preserves user-owned activation state,
|
|
153
|
+
immutable evidence, approvals, credential policies, active OpenSpec changes, and
|
|
154
|
+
project source.
|
|
155
|
+
|
|
156
|
+
Manifest paths are stored as path-part arrays and validated on Windows, macOS,
|
|
157
|
+
and Linux. Generated setup content is identified by managed content hashes; the
|
|
158
|
+
activation version vector and graph hash describe the behavior contract.
|
|
159
|
+
|
|
131
160
|
## GenAI integration configuration
|
|
132
161
|
|
|
133
162
|
Generated GenAI projects expose real configuration boundaries instead of
|
|
@@ -1,269 +1,224 @@
|
|
|
1
|
-
# Repository governance
|
|
1
|
+
# Repository governance and deterministic setup
|
|
2
2
|
|
|
3
|
-
Repository governance is
|
|
4
|
-
`single-maintainer-gitflow` profile
|
|
5
|
-
|
|
3
|
+
Repository governance is enabled by default through the
|
|
4
|
+
`single-maintainer-gitflow` profile; `--governance none` opts out. Initialization
|
|
5
|
+
writes local managed-core artifacts only. It does not run an agent, mutate Git,
|
|
6
|
+
contact GitHub or Azure, configure rulesets, provision runners, deploy, or start
|
|
7
|
+
monitoring.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
Primary path after initialization:
|
|
8
10
|
|
|
9
|
-
```
|
|
10
|
-
liftoff
|
|
11
|
-
|
|
11
|
+
```text
|
|
12
|
+
liftoff init my-project
|
|
13
|
+
cd my-project
|
|
14
|
+
/liftoff-setup
|
|
12
15
|
```
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
`/liftoff-setup` completes the generated bootstrap seed, then enters the
|
|
18
|
+
deterministic Liftoff governance engine and its read-only Phase 0 discovery. The older
|
|
19
|
+
`/liftoff-repository-governance` launcher is a compatibility alias for the same
|
|
20
|
+
engine and user-owned activation state; it is not a separate activation path.
|
|
17
21
|
|
|
18
|
-
##
|
|
22
|
+
## Managed files and user-owned state
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
Enabled governance adds managed-core files:
|
|
21
25
|
|
|
22
26
|
```text
|
|
23
27
|
.liftoff/governance/policy.md
|
|
24
28
|
.liftoff/governance/context.json
|
|
25
29
|
.liftoff/governance/README.md
|
|
26
|
-
.
|
|
27
|
-
.
|
|
30
|
+
.liftoff/governance/phase-graph.json
|
|
31
|
+
.liftoff/governance/compatibility.json
|
|
32
|
+
.liftoff/governance/credential-policy.schema.json
|
|
33
|
+
.github/prompts/liftoff-setup.prompt.md # Copilot selected
|
|
34
|
+
.github/prompts/liftoff-repository-governance.prompt.md # compatibility alias
|
|
35
|
+
.claude/commands/liftoff-setup.md # Claude selected
|
|
36
|
+
.claude/commands/liftoff-repository-governance.md # compatibility alias
|
|
28
37
|
```
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
It covers GitFlow, zero-human-approval repository rules, designated security
|
|
33
|
-
tools, fail-closed checks, immutable release evidence, build-once promotion,
|
|
34
|
-
deployment and rollback, monitoring and health, DORA metrics, ruleset
|
|
35
|
-
sequencing, negative tests, documentation, and workload adaptation.
|
|
36
|
-
|
|
37
|
-
Policy version 5 also fixes platform decisions that generated projects should
|
|
38
|
-
not repeatedly ask users to make:
|
|
39
|
-
|
|
40
|
-
- Dev storage uses LRS; Staging and Production use ZRS. IaC state uses ZRS in
|
|
41
|
-
every environment.
|
|
42
|
-
- Database HA is off in Dev and Staging and zone-redundant in Production.
|
|
43
|
-
- CI uses one user-assigned managed identity with OIDC federation per repository
|
|
44
|
-
and environment, without app registrations or long-lived credentials.
|
|
45
|
-
- The default workload is small and cost-optimised with production safeguards.
|
|
46
|
-
Runtimes remain on Active LTS majors, with grouped dependency updates and
|
|
47
|
-
non-LTS major updates ignored.
|
|
48
|
-
- Slack webhooks are required environment-level GitHub Actions secrets so the
|
|
49
|
-
alert path does not depend on private-vault connectivity.
|
|
50
|
-
- Encrypted local bootstrap state is retained read-only for 30 days after
|
|
51
|
-
verified remote import, then securely deleted with dated evidence.
|
|
52
|
-
- Azure resource-provider namespaces are derived from the approved plan. When
|
|
53
|
-
auto-registration is disabled, each missing required namespace is registered
|
|
54
|
-
explicitly before dependent resources.
|
|
55
|
-
|
|
56
|
-
These are applicable defaults, not reasons to create unused resources. A
|
|
57
|
-
managed service is included only when application code consumes it, after its
|
|
58
|
-
cost and known service limits are stated. When live infrastructure differs from
|
|
59
|
-
IaC, activation planning adapts the IaC and imports the live resource rather
|
|
60
|
-
than creating a parallel stack or forcing replacement.
|
|
61
|
-
|
|
62
|
-
## Private Staging qualification
|
|
63
|
-
|
|
64
|
-
DAST for a privately networked Staging environment uses an ephemeral
|
|
65
|
-
GitHub-hosted larger runner with Azure VNet injection. Activation reuses a
|
|
66
|
-
suitable existing repository assignment. If none exists, policy version 5
|
|
67
|
-
permits one narrow post-approval exception to provision the Azure network
|
|
68
|
-
setting, organisation hosted-compute network configuration, selected-access
|
|
69
|
-
runner group, and bounded larger runner required by that repository.
|
|
70
|
-
|
|
71
|
-
Phase 0 first proves that private Staging DAST applies. It then discovers the
|
|
72
|
-
repository's Staging subscription and tenant, existing runner resources, Azure
|
|
73
|
-
and GitHub write authority, enterprise network policy, billing, state, names,
|
|
74
|
-
address space, DNS, routing, costs, limits, and teardown ownership. Missing
|
|
75
|
-
authority or an unresolved input blocks provisioning without partial mutation.
|
|
76
|
-
No self-hosted runner is substituted.
|
|
77
|
-
|
|
78
|
-
Every Azure runner-network resource, its state, egress cost, and teardown owner
|
|
79
|
-
remain inside the repository's Staging subscription. The design cannot share a
|
|
80
|
-
firewall, hub, route, state, or lifecycle with another repository or
|
|
81
|
-
subscription. GitHub resources exist at organisation level but grant selected
|
|
82
|
-
access only to the target repository and required workflows.
|
|
83
|
-
|
|
84
|
-
The delegated runner subnet disables implicit default outbound access, denies
|
|
85
|
-
unsolicited inbound connectivity, and uses exactly one egress mode:
|
|
86
|
-
|
|
87
|
-
- Azure Firewall Basic only when an applicable policy requires domain-restricted
|
|
88
|
-
egress. Its HTTPS rules use a current GitHub meta domain set without the
|
|
89
|
-
retired static-IP template or TLS interception.
|
|
90
|
-
- Azure NAT Gateway otherwise, with required protocols constrained by an NSG.
|
|
91
|
-
NAT and NSG controls do not filter HTTPS by domain.
|
|
92
|
-
|
|
93
|
-
NAT Gateway cannot be attached to a firewall-routed runner subnet because it
|
|
94
|
-
takes precedence and would bypass the firewall. The approved topology must also
|
|
95
|
-
prove non-overlapping address space, same-subscription routing or peering,
|
|
96
|
-
private DNS, security rules, and live private Staging reachability.
|
|
97
|
-
|
|
98
|
-
A standard hosted preflight verifies the assignment and labels before scheduling
|
|
99
|
-
DAST. Azure and GitHub resources, associations, egress, DNS, and reachability
|
|
100
|
-
must all be read back successfully. Missing or partial evidence blocks
|
|
101
|
-
qualification rather than leaving a required job queued or reporting success.
|
|
102
|
-
Teardown reverses those dependencies and removes the Azure network only after
|
|
103
|
-
GitHub scheduling, assignment, and service associations are gone.
|
|
104
|
-
|
|
105
|
-
### Azure resource-provider readiness
|
|
106
|
-
|
|
107
|
-
Phase 0 derives the minimal namespace inventory from every approved Azure
|
|
108
|
-
resource type and records AzureRM's registration mode and the execution
|
|
109
|
-
identity's subscription registration permission. A hosted-runner network always
|
|
110
|
-
requires at least `Microsoft.Network` and `GitHub.Network`; additional providers
|
|
111
|
-
are included only when approved state, identity, monitoring, or application
|
|
112
|
-
resources use them.
|
|
113
|
-
|
|
114
|
-
When AzureRM automatic registration is enabled and sufficient, no duplicate
|
|
115
|
-
explicit resources are added. When
|
|
116
|
-
`resource_provider_registrations = "none"` disables it, every missing required
|
|
117
|
-
namespace is registered explicitly. Dependent and billable resources remain
|
|
118
|
-
blocked until live subscription readback reports each namespace as
|
|
119
|
-
`Registered`.
|
|
120
|
-
|
|
121
|
-
Every explicit resource has a direct or transitive dependency on its namespace
|
|
122
|
-
registration. Existing registrations are no-ops. Pending, unauthorized,
|
|
123
|
-
unregistering, or failed states require a revised no-apply plan rather than
|
|
124
|
-
partial provisioning. Successful registrations remain subscription capabilities
|
|
125
|
-
during repository teardown and are not automatically unregistered.
|
|
126
|
-
|
|
127
|
-
Subscription features are narrower than provider namespaces. A
|
|
128
|
-
`SubscriptionNotRegisteredForFeature` error does not authorize registering the
|
|
129
|
-
named feature unless the approved resource design intentionally uses it.
|
|
130
|
-
Unexpected feature requests require correction of the resource properties,
|
|
131
|
-
provider behavior, or API shape and a revised no-apply plan.
|
|
132
|
-
|
|
133
|
-
Ordinary Firewall and NAT Standard public IPs do not require BYOIP. If such a
|
|
134
|
-
resource requests `Microsoft.Network/AllowBringYourOwnPublicIpAddress` without a
|
|
135
|
-
custom IP prefix, the plan must remove accidental BYOIP properties or use a
|
|
136
|
-
supported API shape; it must not register BYOIP merely to retry.
|
|
137
|
-
|
|
138
|
-
Network service-tag rules also require semantic validation.
|
|
139
|
-
`AzurePlatformDNS` is deny-only for intentionally disabling Azure platform DNS,
|
|
140
|
-
not a valid Allow target. Default platform DNS needs no explicit NSG allow.
|
|
141
|
-
Custom resolvers instead receive TCP and UDP port 53 allows to their exact IP
|
|
142
|
-
addresses.
|
|
143
|
-
|
|
144
|
-
### Private state bootstrap and retention
|
|
145
|
-
|
|
146
|
-
Phase 0 prefers an existing approved private execution path to the
|
|
147
|
-
repository-owned ZRS backend. When public access is disabled and no such path
|
|
148
|
-
exists, an approved governance change may use encrypted local OpenTofu state for
|
|
149
|
-
only the minimum networking, private endpoint, DNS, network setting, and
|
|
150
|
-
restricted runner resources needed to establish access. This
|
|
151
|
-
`bootstrap-local` phase is not remote-ready and cannot authorize application
|
|
152
|
-
provisioning.
|
|
153
|
-
|
|
154
|
-
The local state remains gitignored, single-writer, encrypted on the approved
|
|
155
|
-
workstation, and is never transferred through GitHub artifacts, repository
|
|
156
|
-
secrets, or ordinary messages. From the exact private runner, reviewed import
|
|
157
|
-
declarations adopt the resources into an empty ZRS backend without copying the
|
|
158
|
-
local state file.
|
|
159
|
-
|
|
160
|
-
Remote import is complete only after private Blob access, exact live-to-state
|
|
161
|
-
resource identity, state locking, Blob versioning, and a clean-checkout
|
|
162
|
-
no-change plan are verified. Failure starts no retention clock and keeps normal
|
|
163
|
-
provisioning blocked.
|
|
164
|
-
|
|
165
|
-
At successful verification, the local state becomes evidence-only and read-only
|
|
166
|
-
for exactly 30 days. It cannot run plan or apply. At expiry, its encryption key
|
|
167
|
-
and encrypted files are removed, along with every approved temporary copy. A
|
|
168
|
-
dated record captures the state identity or checksum, verification evidence,
|
|
169
|
-
scheduled and actual deletion, operator, method, and outcome without containing
|
|
170
|
-
state data or secrets.
|
|
171
|
-
|
|
172
|
-
## Release identity and automated completion
|
|
173
|
-
|
|
174
|
-
Staging qualifies the release or hotfix candidate commit and binds it to the
|
|
175
|
-
version, artifact digest, and evidence-bundle digest. A later true merge into
|
|
176
|
-
`main` necessarily has a different SHA. Production verifies that the merge
|
|
177
|
-
incorporates the exact qualified candidate, promotes the identical artifact,
|
|
178
|
-
and records both identities:
|
|
39
|
+
User-owned execution state is separate and is never advanced by
|
|
40
|
+
`liftoff update`:
|
|
179
41
|
|
|
180
42
|
```text
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
+-> deployment -> tag and GitHub Release
|
|
43
|
+
governance/activation-state.json
|
|
44
|
+
governance/approvals/
|
|
45
|
+
governance/evidence/
|
|
46
|
+
governance/credentials/preflight-policy.json
|
|
186
47
|
```
|
|
187
48
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
checks. Because `GITHUB_TOKEN`-created events do not normally start more
|
|
193
|
-
workflows, the coordinating workflow explicitly dispatches validation for the
|
|
194
|
-
back-merge head and any required post-merge work for the resulting SHA. It does
|
|
195
|
-
not push directly to a protected branch or rely on a tag push. Tag creation,
|
|
196
|
-
Release publication, and durable evidence stay in the successful production
|
|
197
|
-
workflow.
|
|
198
|
-
|
|
199
|
-
`context.json` contains generated project facts only. GitHub repository state,
|
|
200
|
-
runner access, licensed features, deployments, monitoring, alert routes,
|
|
201
|
-
traffic, and rollout capabilities remain `undiscovered`. Power Apps context
|
|
202
|
-
explicitly marks Liftoff backend, Docker, OpenTofu, custom container promotion,
|
|
203
|
-
and API DAST as inapplicable.
|
|
204
|
-
|
|
205
|
-
## Activate after commit and push
|
|
206
|
-
|
|
207
|
-
1. Review the policy and context.
|
|
208
|
-
2. Commit the project and push it to the intended GitHub repository.
|
|
209
|
-
3. Run `/liftoff-repository-governance` with a selected agent.
|
|
210
|
-
4. The agent performs read-only Phase 0 and reports repository identity,
|
|
211
|
-
artifacts, working commands, refs, workflows and exact checks, rulesets,
|
|
212
|
-
releases, environments, security, runners, deployments, monitoring, alerts,
|
|
213
|
-
health depth, platform capabilities, gaps, and inapplicable controls. When
|
|
214
|
-
private Staging DAST applies without a suitable runner, it also reports the
|
|
215
|
-
complete subscription-local topology, one explicit egress mode, authority,
|
|
216
|
-
costs, limits, verification, and teardown plan.
|
|
217
|
-
5. The agent proposes the current `main` SHA as the activation baseline,
|
|
218
|
-
presents an ordered plan, and stops.
|
|
219
|
-
6. Explicitly approve or revise the conversational plan. This is not a human
|
|
220
|
-
merge or deployment approval gate.
|
|
221
|
-
7. After approval, the agent creates a new OpenSpec or Spec Kit governance
|
|
222
|
-
change, proves required contexts green and deliberately red, applies
|
|
223
|
-
repository-scoped rulesets last, and reads live enforcement back.
|
|
224
|
-
|
|
225
|
-
The user-owned `governance/activation-baseline.json` is created only after
|
|
226
|
-
approval. Liftoff never owns or recreates it or the agent-created governance
|
|
227
|
-
change. Complete local handoffs say `handoff-generated`, partial adoptions say
|
|
228
|
-
`handoff-partial`, and neither state means `active`.
|
|
49
|
+
The complete policy is packaged at
|
|
50
|
+
[`assets/governance/single-maintainer-gitflow/policy.md`](../assets/governance/single-maintainer-gitflow/policy.md).
|
|
51
|
+
Policy version 6 treats numbered policy sections as capability chapters, not
|
|
52
|
+
execution order. The managed phase graph is the sole execution-order authority.
|
|
229
53
|
|
|
230
|
-
##
|
|
54
|
+
## Canonical phase graph
|
|
55
|
+
|
|
56
|
+
The activation graph is packaged as `.liftoff/governance/phase-graph.json` and
|
|
57
|
+
records phase IDs, dependencies, applicability, allowed mutations, evidence,
|
|
58
|
+
approvals, rollback boundaries, and terminal states:
|
|
231
59
|
|
|
232
|
-
|
|
233
|
-
|
|
60
|
+
```text
|
|
61
|
+
seed-valid
|
|
62
|
+
-> seed-verified
|
|
63
|
+
-> seed-archived
|
|
64
|
+
-> committed
|
|
65
|
+
-> pushed
|
|
66
|
+
-> phase-0-complete
|
|
67
|
+
-> activation-approved
|
|
68
|
+
-> credential-ready
|
|
69
|
+
-> provider-ready
|
|
70
|
+
-> state-path-selected
|
|
71
|
+
|-> existing-private-path ----------------------|
|
|
72
|
+
`-> bootstrap-local -> runner-ready |
|
|
73
|
+
-> private-backend-proof |
|
|
74
|
+
-> remote-import-verified --|
|
|
75
|
+
-> remote-ready
|
|
76
|
+
-> application-foundation
|
|
77
|
+
-> workflow-source-ready
|
|
78
|
+
-> dev-proof
|
|
79
|
+
-> staging-qualified
|
|
80
|
+
-> production-rehearsed
|
|
81
|
+
-> green-red-proof
|
|
82
|
+
-> enforcement-approved
|
|
83
|
+
-> rulesets-applied
|
|
84
|
+
-> live-readback
|
|
85
|
+
-> bootstrap-state-disposed
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
If policy prose, generated tasks, or an agent response orders a transition
|
|
89
|
+
differently, the graph wins. Provider readiness precedes `bootstrap-local`;
|
|
90
|
+
restricted runner readiness precedes private backend proof; private backend proof
|
|
91
|
+
precedes declarative remote import; and only an existing private path or verified
|
|
92
|
+
remote import can satisfy `remote-ready`.
|
|
93
|
+
|
|
94
|
+
## Bootstrap seed and local baseline
|
|
95
|
+
|
|
96
|
+
Before commit/push or Phase 0, setup completes, syncs, and archives the generated
|
|
97
|
+
`bootstrap-<project>` OpenSpec seed. It runs only local, applicable checks:
|
|
98
|
+
|
|
99
|
+
- `liftoff validate`
|
|
100
|
+
- backend tests from the generated README
|
|
101
|
+
- frontend build when a frontend exists
|
|
102
|
+
- `docker compose config -q` when Compose exists
|
|
103
|
+
- `tofu fmt -check -recursive`
|
|
104
|
+
- `tofu init -backend=false`
|
|
105
|
+
- `tofu validate`
|
|
106
|
+
- strict OpenSpec validation
|
|
107
|
+
|
|
108
|
+
Absent components are recorded as inapplicable. The baseline never starts
|
|
109
|
+
containers, runs a live `tofu plan` or `tofu apply`, deploys, mutates GitHub, or
|
|
110
|
+
requires cloud credentials. A failed check keeps the seed active; rerun
|
|
111
|
+
`/liftoff-setup` after remediation and verified phases are not repeated.
|
|
112
|
+
|
|
113
|
+
## Questions and approval envelopes
|
|
114
|
+
|
|
115
|
+
Deterministic defaults and discovered facts do not become conversational
|
|
116
|
+
questions. Setup may ask only at these authority gates:
|
|
117
|
+
|
|
118
|
+
1. repository creation, initial commit, remote, or push;
|
|
119
|
+
2. credential enrollment;
|
|
120
|
+
3. billed infrastructure, policy exceptions, and cost ceiling;
|
|
121
|
+
4. final ruleset enforcement;
|
|
122
|
+
5. destructive cleanup, including day-30 bootstrap-state disposal;
|
|
123
|
+
6. external platform blockers that require changed authority or design.
|
|
124
|
+
|
|
125
|
+
Every approval envelope records the reviewed plan digest, allowed resource
|
|
126
|
+
types, destinations, permissions, cost ceiling, destructive scope, policy
|
|
127
|
+
exceptions, expiry, and baseline SHA. Retries inside the same envelope do not
|
|
128
|
+
ask again; expanded resources, destinations, permissions, cost, exceptions, or
|
|
129
|
+
destructive effects require a new approval.
|
|
130
|
+
|
|
131
|
+
## Credentials for runner preflight
|
|
132
|
+
|
|
133
|
+
When `GITHUB_TOKEN` cannot read required hosted-runner metadata, setup first
|
|
134
|
+
prefers an existing verified selected-repository GitHub App installation with the
|
|
135
|
+
required read permissions. Liftoff does not install or broaden an App.
|
|
136
|
+
|
|
137
|
+
If no approved App is available, setup guides one fine-grained PAT with exactly:
|
|
138
|
+
|
|
139
|
+
| Field | Value |
|
|
140
|
+
| --- | --- |
|
|
141
|
+
| Display name | `<repo>-runner-preflight-read` |
|
|
142
|
+
| Repository secret | `RUNNER_CONFIGURATION_READ_TOKEN` |
|
|
143
|
+
| Lifetime | 30 days |
|
|
144
|
+
| Repository scope | current repository only |
|
|
145
|
+
| Repository permission | metadata read |
|
|
146
|
+
| Organization permissions | hosted-runner read and network-configuration read |
|
|
147
|
+
| Writes | none |
|
|
148
|
+
| Workflow/job allowlist | `.github/workflows/bootstrap-import-preflight.yml` job `bootstrap-import-preflight`; `.github/workflows/private-dast-preflight.yml` job `private-dast-preflight` |
|
|
149
|
+
|
|
150
|
+
Enter the value only through Liftoff's masked input. Never paste or show the
|
|
151
|
+
value in chat, argv, command arguments, logs, evidence, files, or screenshots. A value
|
|
152
|
+
that appears in any of those places is compromised and must be manually revoked
|
|
153
|
+
and rotated before setup can continue.
|
|
154
|
+
|
|
155
|
+
The recorded credential policy is payload-free: it stores auth kind, display
|
|
156
|
+
name, secret name, owner, repository, expiry, rotation lead, permissions,
|
|
157
|
+
allowed workflows/jobs, non-forwarding rules, and readback evidence, never the
|
|
158
|
+
secret value.
|
|
159
|
+
|
|
160
|
+
## Evidence authority and active changes
|
|
161
|
+
|
|
162
|
+
Task checkboxes are a projection of phase state, not authority. Evidence
|
|
163
|
+
documents carry repository identity, activation version vector, graph hash, phase
|
|
164
|
+
contract digest, input digest, baseline SHA, phase ID, timestamp, producer, and
|
|
165
|
+
result. Setup and `liftoff governance verify` reject missing, stale,
|
|
166
|
+
contradictory, future-version, or graph-incompatible evidence.
|
|
167
|
+
|
|
168
|
+
There may be only one active governance source of truth. An unfinished bootstrap
|
|
169
|
+
seed blocks Phase 0. Exactly one compatible active governance change is resumed.
|
|
170
|
+
Multiple overlapping changes require a schema-valid supersession or archive
|
|
171
|
+
record before any phase advances.
|
|
172
|
+
|
|
173
|
+
Managed updates install new policy, graph, schema, compatibility metadata, setup
|
|
174
|
+
integrations, and aliases without touching user-owned state. When a policy,
|
|
175
|
+
activation-contract, schema, or graph-hash change affects active work, status
|
|
176
|
+
reports `reconciliation-required`, invalidates only affected descendants, and
|
|
177
|
+
waits for explicit acknowledgement of the current compatible identity and exact
|
|
178
|
+
graph hash.
|
|
179
|
+
|
|
180
|
+
## Private staging and bootstrap retention
|
|
181
|
+
|
|
182
|
+
Private Staging DAST uses an ephemeral GitHub-hosted larger runner with Azure
|
|
183
|
+
VNet injection only when genuinely applicable. Phase 0 discovers repository,
|
|
184
|
+
subscription, authority, billing, network, DNS, cost, teardown, and capability
|
|
185
|
+
facts read-only. If DAST is inapplicable, no runner networking is provisioned.
|
|
186
|
+
|
|
187
|
+
When a private ZRS backend cannot be reached and no existing private management
|
|
188
|
+
path is approved, the bounded `bootstrap-local` branch may create only the
|
|
189
|
+
access-establishing resources needed to reach the backend. Local bootstrap state
|
|
190
|
+
is encrypted, gitignored, single-writer, never uploaded or copied through GitHub
|
|
191
|
+
artifacts or secrets, and cannot authorize application provisioning.
|
|
192
|
+
|
|
193
|
+
After verified declarative import, backend identity parity, state locking, Blob
|
|
194
|
+
versioning, and a clean-checkout no-change plan, local state becomes read-only
|
|
195
|
+
evidence for exactly 30 days. Disposal deletes the encryption key and approved
|
|
196
|
+
temporary copies and records a dated non-secret outcome. Provider registrations
|
|
197
|
+
remain retained subscription capabilities and are not unregistered during
|
|
198
|
+
teardown.
|
|
199
|
+
|
|
200
|
+
## Commands
|
|
201
|
+
|
|
202
|
+
The generated setup integrations call only strict, project-aware CLI commands:
|
|
234
203
|
|
|
235
204
|
```bash
|
|
236
|
-
liftoff
|
|
237
|
-
liftoff
|
|
205
|
+
liftoff governance status --json
|
|
206
|
+
liftoff governance plan --json
|
|
207
|
+
liftoff governance apply-next --json --execute
|
|
208
|
+
liftoff governance resume --json
|
|
209
|
+
liftoff governance verify --json
|
|
238
210
|
```
|
|
239
211
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
Projects
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
Setting `"governanceProfile": "none"` stops future rendering. Previously managed
|
|
254
|
-
handoff files are reported once as orphans and left on disk; Liftoff never
|
|
255
|
-
deletes them automatically or changes live repository settings.
|
|
256
|
-
|
|
257
|
-
## Capability gaps
|
|
258
|
-
|
|
259
|
-
Phase 0 must report missing GitHub licenses, runner-provisioning authority,
|
|
260
|
-
VNet-injected assignment or reachability, Staging access, monitoring routes,
|
|
261
|
-
parallel-version mechanisms, or statistically meaningful canary traffic. It
|
|
262
|
-
must mark controls inapplicable or blocked rather than creating a skipped,
|
|
263
|
-
hanging, partial, duplicate, or success-shaped placeholder.
|
|
264
|
-
|
|
265
|
-
The official SLSA L3 generator is the policy's only action SHA-pinning
|
|
266
|
-
exception because its reusable workflow contains mutable internal references.
|
|
267
|
-
The outer call is pinned as tightly as supported and the exact exception is
|
|
268
|
-
narrow and expiring. It does not weaken pinning for any other action, create a
|
|
269
|
-
second vulnerability allowlist, or make Grype a blocking gate.
|
|
212
|
+
`status`, `plan`, and `verify` are read-only. `apply-next` previews mutations
|
|
213
|
+
unless `--execute` is supplied, and even then executes at most one graph-ready,
|
|
214
|
+
evidence-ready, approved phase. Unknown subcommands, flags, or extra positionals
|
|
215
|
+
fail before project discovery or mutation.
|
|
216
|
+
|
|
217
|
+
## Existing projects
|
|
218
|
+
|
|
219
|
+
Projects without `governanceProfile` normalize to the enabled default during
|
|
220
|
+
read, then `liftoff update --check` previews manifest v7 and managed-core drift.
|
|
221
|
+
Plain `liftoff update` writes v7 only after preflights pass. It never provisions
|
|
222
|
+
Azure or GitHub resources and never advances activation state. Setting
|
|
223
|
+
`"governanceProfile": "none"` stops future rendering; previously managed files
|
|
224
|
+
become reported orphans and remain on disk for manual review.
|