@msn-control/liftoff 0.6.1 → 0.7.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/README.md +6 -0
- package/dist/args.js +14 -1
- package/dist/args.js.map +1 -1
- package/dist/cli.d.ts +21 -1
- package/dist/cli.js +85 -17
- package/dist/cli.js.map +1 -1
- package/dist/commands.js +124 -135
- package/dist/commands.js.map +1 -1
- package/dist/file-system.d.ts +1 -0
- package/dist/file-system.js +11 -2
- package/dist/file-system.js.map +1 -1
- package/dist/interactive.d.ts +0 -5
- package/dist/interactive.js +0 -66
- package/dist/interactive.js.map +1 -1
- package/dist/telemetry/config.d.ts +20 -0
- package/dist/telemetry/config.js +105 -0
- package/dist/telemetry/config.js.map +1 -0
- package/dist/telemetry/contract.d.ts +33 -0
- package/dist/telemetry/contract.js +82 -0
- package/dist/telemetry/contract.js.map +1 -0
- package/dist/telemetry/index.d.ts +19 -0
- package/dist/telemetry/index.js +97 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/templates.js +2 -2
- package/docs/cli-reference.md +41 -21
- package/docs/configuration-and-manifests.md +3 -4
- package/docs/existing-repositories.md +6 -6
- package/docs/safety-and-consent.md +34 -17
- package/docs/spec-workflows-and-agents.md +3 -2
- package/docs/telemetry.md +168 -0
- package/docs/troubleshooting.md +7 -9
- package/docs/workloads.md +4 -0
- package/package.json +1 -1
- package/dist/update-impact.d.ts +0 -23
- package/dist/update-impact.js +0 -127
- package/dist/update-impact.js.map +0 -1
package/docs/cli-reference.md
CHANGED
|
@@ -24,8 +24,9 @@ plan -> init or migrate -> validate and doctor -> update -> dev and infra helper
|
|
|
24
24
|
| `liftoff migrate <source>` | Creates a new sibling scaffold and filtered source copy without changing the source |
|
|
25
25
|
| `liftoff validate [project]` | Validates manifest identity, durable files, workload metadata, and framework markers |
|
|
26
26
|
| `liftoff doctor [project]` | Runs read-only workload-derived project and workstation diagnostics |
|
|
27
|
-
| `liftoff update [project]` |
|
|
28
|
-
| `liftoff update --
|
|
27
|
+
| `liftoff update [project]` | Applies safe managed drift immediately, preserves unforced conflicts and orphans, and records the resulting manifest |
|
|
28
|
+
| `liftoff update --check` | Reports drift without preflight or mutation; exits 0 when clean and 2 when drift exists |
|
|
29
|
+
| `liftoff update --force` | Applies safe changes and overwrites only the exact guarded conflicts reported by update |
|
|
29
30
|
| `liftoff dev` | Prints workload-appropriate local development commands; it does not execute them |
|
|
30
31
|
| `liftoff infra` | Prints OpenTofu guidance for API workloads and reports infrastructure as not applicable for Power Apps |
|
|
31
32
|
| `liftoff patterns` | Lists GenAI patterns |
|
|
@@ -64,30 +65,46 @@ Consent options are documented in [safety and consent](safety-and-consent.md).
|
|
|
64
65
|
|
|
65
66
|
```bash
|
|
66
67
|
liftoff update
|
|
68
|
+
liftoff update --force
|
|
67
69
|
liftoff update --json
|
|
68
|
-
liftoff update --
|
|
69
|
-
liftoff update --
|
|
70
|
+
liftoff update --check
|
|
71
|
+
liftoff update --check --json
|
|
70
72
|
```
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
preflight or write.
|
|
74
|
+
Plain `liftoff update` is imperative and prompt-free. It applies safe new,
|
|
75
|
+
missing, untouched-upgrade, clean-move, and recorded-state changes in
|
|
76
|
+
interactive terminals, redirected streams, and automation. Local or user-owned
|
|
77
|
+
conflicts are skipped and reported. Orphans are reported without deletion.
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
Use `--check` whenever no project bytes may change. Human check mode prints each
|
|
80
|
+
drift state and recommends plain update for safe changes or a reviewed
|
|
81
|
+
`--force` invocation for conflicts. `--check --force` is invalid because check
|
|
82
|
+
mode never authorizes writes.
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
successful overwrite; commit or copy local work first.
|
|
84
|
+
`--json` selects output format, not safety. `liftoff update --json` applies safe
|
|
85
|
+
changes and emits the versioned apply result. `liftoff update --check --json`
|
|
86
|
+
is the read-only automation gate.
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
Update never installs dependencies. Transaction snapshots restore a failed
|
|
89
|
+
update, but Liftoff retains no backup after a successful overwrite; commit or
|
|
90
|
+
copy local work before using `--force`. Force does not permit workload, API
|
|
91
|
+
stack, GenAI pattern, framework, selected-agent, or user-supplied Power Apps
|
|
92
|
+
starter identity changes, and it cannot bypass project-boundary, symlink,
|
|
93
|
+
structural-collision, or manifest guards.
|
|
94
|
+
|
|
95
|
+
### Migration from 0.6.x
|
|
96
|
+
|
|
97
|
+
The `--apply` flag was removed in 0.7.0. These are historical 0.6.x commands,
|
|
98
|
+
not current syntax:
|
|
99
|
+
|
|
100
|
+
| Historical 0.6.x command | 0.7.0 replacement |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| `liftoff update` when used as a read-only check | `liftoff update --check` |
|
|
103
|
+
| `liftoff update --apply` | `liftoff update` |
|
|
104
|
+
| `liftoff update --apply --force` | `liftoff update --force` |
|
|
105
|
+
|
|
106
|
+
Invoking removed syntax fails during argument parsing, before project discovery
|
|
107
|
+
or filesystem access.
|
|
91
108
|
|
|
92
109
|
## JSON and exit codes
|
|
93
110
|
|
|
@@ -97,15 +114,18 @@ Machine-readable maintenance contracts bypass decorative presentation:
|
|
|
97
114
|
liftoff validate --json
|
|
98
115
|
liftoff doctor --json
|
|
99
116
|
liftoff update --json
|
|
117
|
+
liftoff update --check --json
|
|
100
118
|
```
|
|
101
119
|
|
|
102
120
|
Each JSON object has a top-level numeric `schemaVersion`.
|
|
121
|
+
Operational warnings, such as a dirty-worktree warning before JSON apply, are
|
|
122
|
+
written to stderr so stdout remains one parseable JSON object.
|
|
103
123
|
|
|
104
124
|
Exit codes:
|
|
105
125
|
|
|
106
126
|
- `0`: success or a clean check.
|
|
107
127
|
- `1`: invalid input, unsafe state, or command failure.
|
|
108
|
-
- `2`:
|
|
128
|
+
- `2`: explicit update check mode found drift.
|
|
109
129
|
|
|
110
130
|
Raw installer, framework, and dependency child stdout and stderr are forwarded
|
|
111
131
|
unchanged.
|
|
@@ -67,10 +67,9 @@ Readers support schemas v2, v3, and v4:
|
|
|
67
67
|
- V3 normalizes flat GenAI or API identity plus framework and agent metadata.
|
|
68
68
|
- V4 represents the discriminated workload model, including Power Apps.
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
conflicts retain their recorded hashes.
|
|
70
|
+
`liftoff update --check`, including `--check --json`, leaves an old manifest
|
|
71
|
+
byte-for-byte unchanged. A successful plain update writes v4 only after the
|
|
72
|
+
file transaction succeeds. Skipped conflicts retain their recorded hashes.
|
|
74
73
|
|
|
75
74
|
## Artifact ownership
|
|
76
75
|
|
|
@@ -64,15 +64,15 @@ Use:
|
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
liftoff validate
|
|
67
|
+
liftoff update --check
|
|
67
68
|
liftoff update
|
|
68
|
-
liftoff update --apply
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
71
|
+
Use `--check` first when the invocation must be read-only. Plain update applies
|
|
72
|
+
safe managed changes immediately and without prompting in terminals and
|
|
73
|
+
automation, while preserving conflicts and orphans. Review every reported
|
|
74
|
+
conflict and commit or copy local work before choosing `liftoff update --force`.
|
|
75
|
+
For CI drift gates, use `liftoff update --check --json`.
|
|
76
76
|
|
|
77
77
|
## Existing non-Liftoff application
|
|
78
78
|
|
|
@@ -8,7 +8,7 @@ project dependencies. No one permission implies another.
|
|
|
8
8
|
| Flag | Authorizes | Does not authorize |
|
|
9
9
|
| --- | --- | --- |
|
|
10
10
|
| `--yes` | Project defaults and plan confirmation | File replacement, machine installs, or project dependencies |
|
|
11
|
-
| `--force` |
|
|
11
|
+
| `--force` | During init, listed regular-file replacements; during update, exact reported conflicts | Manifest guards, symlinks, structural collisions, tools, dependencies, or non-empty migration targets |
|
|
12
12
|
| `--install-tools` | Allowlisted workstation installation commands | Project decisions, overwrites, or project dependencies |
|
|
13
13
|
| `--install-dependencies` | Locked project-local dependency commands after a successful merge | Machine tools, project decisions, or overwrites |
|
|
14
14
|
|
|
@@ -50,11 +50,10 @@ Individual project files use temporary-file replacement. Initialization keeps
|
|
|
50
50
|
backups for replaced files and records created files and directories. A handled
|
|
51
51
|
merge failure restores or removes those entries in reverse order.
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
state.
|
|
53
|
+
Plain `liftoff update` preflights all affected paths and applies generated file,
|
|
54
|
+
move, delete, and manifest mutations as one rollback-capable transaction.
|
|
55
|
+
Schema upgrades are committed only after the other mutations succeed. A
|
|
56
|
+
corrected retry converges from the restored state.
|
|
58
57
|
|
|
59
58
|
If automatic rollback itself cannot safely restore a path because another
|
|
60
59
|
process changed it, Liftoff reports the incomplete rollback rather than
|
|
@@ -65,24 +64,25 @@ does not retain them as backups after success.
|
|
|
65
64
|
|
|
66
65
|
## Update ownership
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
Update mode is selected explicitly rather than from terminal interactivity:
|
|
69
68
|
|
|
70
69
|
- Clean generated files remain unchanged.
|
|
71
|
-
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
70
|
+
- Plain `liftoff update` immediately applies safe new, missing,
|
|
71
|
+
untouched-upgrade, clean-move, and recorded-state changes without prompting,
|
|
72
|
+
including with redirected input or output.
|
|
73
|
+
- `liftoff update --check` is read-only and performs no preflight or mutation.
|
|
74
|
+
- `liftoff update --json` applies safe changes and returns an apply result;
|
|
75
|
+
`liftoff update --check --json` is the read-only machine drift gate.
|
|
76
76
|
- Developer edits that also differ from the current template are conflicts.
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
- Default update skips conflicts and lists them by portable relative path.
|
|
78
|
+
After reviewing every listed overwrite, `liftoff update --force` extends the
|
|
79
|
+
transaction only to those guarded conflicts.
|
|
80
80
|
- Orphans are reported and left on disk for manual review.
|
|
81
81
|
- Dependency definitions may be updated, but update never installs
|
|
82
82
|
dependencies.
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
`--force` cannot be combined with `--check` and cannot weaken project-boundary,
|
|
85
|
+
symlink, collision, manifest, or transaction guards.
|
|
86
86
|
|
|
87
87
|
Power Apps reconciliation reads only the packaged immutable starter. It does
|
|
88
88
|
not fetch the upstream repository. Workload kind and user-edited starter
|
|
@@ -98,6 +98,23 @@ does not claim framework-owned files in durable artifact hashes.
|
|
|
98
98
|
One-time seed content is also omitted from durable hashes so it can follow its
|
|
99
99
|
own lifecycle after generation.
|
|
100
100
|
|
|
101
|
+
## Telemetry boundary
|
|
102
|
+
|
|
103
|
+
Liftoff sends only a recognized command name, CLI version, and zero/nonzero
|
|
104
|
+
outcome after a command completes. It creates no persistent installation or
|
|
105
|
+
session identifier and sends no arguments, paths, project data, errors, timing,
|
|
106
|
+
or host details.
|
|
107
|
+
|
|
108
|
+
Telemetry is enabled by default after a one-time disclosure. Set
|
|
109
|
+
`LIFTOFF_TELEMETRY=0` or `DO_NOT_TRACK=1` to disable it; `CI=true` disables it
|
|
110
|
+
automatically. Delivery is one bounded HTTPS attempt and cannot change command
|
|
111
|
+
output or exit status.
|
|
112
|
+
|
|
113
|
+
Azure necessarily handles a source network address while routing HTTPS, but
|
|
114
|
+
Liftoff does not include it in the event, derive geolocation from it, or persist
|
|
115
|
+
it in the product telemetry table. See [telemetry and privacy](telemetry.md) for
|
|
116
|
+
the exact fields, Azure boundary, OpenTofu deployment, and 180-day retention.
|
|
117
|
+
|
|
101
118
|
## Credentials and external actions
|
|
102
119
|
|
|
103
120
|
Generated files contain configuration boundaries, not real credentials.
|
|
@@ -88,5 +88,6 @@ invoke `/create-code-app`. The plugin's connector and deployment skills remain
|
|
|
88
88
|
available for post-creation work.
|
|
89
89
|
|
|
90
90
|
Changing the valid plugin preference in `liftoff.config.json` is reconciled by
|
|
91
|
-
`liftoff update`; it updates generated guidance and manifest
|
|
92
|
-
creating API or infrastructure artifacts.
|
|
91
|
+
plain `liftoff update`; it immediately updates generated guidance and manifest
|
|
92
|
+
intent without creating API or infrastructure artifacts. Use
|
|
93
|
+
`liftoff update --check` to inspect that drift without writing.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Telemetry and privacy
|
|
2
|
+
|
|
3
|
+
Liftoff collects a small aggregate event to understand which CLI commands are
|
|
4
|
+
useful and whether they exit with zero or nonzero status. Telemetry is enabled
|
|
5
|
+
by default, disclosed before the first eligible command, and never required for
|
|
6
|
+
the CLI to work. It creates no persistent installation or session identifier.
|
|
7
|
+
|
|
8
|
+
## Event contract
|
|
9
|
+
|
|
10
|
+
Each recognized command can send at most one event after it finishes:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"schemaVersion": 1,
|
|
15
|
+
"event": "command_executed",
|
|
16
|
+
"command": "infra:plan",
|
|
17
|
+
"cliVersion": "0.6.1",
|
|
18
|
+
"outcome": "success"
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`outcome` is `success` for exit code zero and `failure` for every nonzero exit
|
|
23
|
+
code. It is an exit-status class, not an error diagnosis. Help requests are
|
|
24
|
+
recorded as `help`, and rejected input that never resolves to a recognized
|
|
25
|
+
command is not recorded.
|
|
26
|
+
|
|
27
|
+
Liftoff does **not** send:
|
|
28
|
+
|
|
29
|
+
- An installation, user, device, or session identifier.
|
|
30
|
+
- A client timestamp or duration.
|
|
31
|
+
- Arguments, flags, paths, project names, config values, manifests, or generated
|
|
32
|
+
content.
|
|
33
|
+
- Error text, stack traces, operating-system details, Node.js version, cloud,
|
|
34
|
+
workload, region, or environment choices.
|
|
35
|
+
- A source IP address or derived location in the event.
|
|
36
|
+
|
|
37
|
+
Liftoff creates no telemetry queue and stores no event locally. Its only local
|
|
38
|
+
telemetry state is a numeric disclosure version in the platform configuration
|
|
39
|
+
directory.
|
|
40
|
+
|
|
41
|
+
## Disable telemetry
|
|
42
|
+
|
|
43
|
+
Set either variable before running Liftoff:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
export LIFTOFF_TELEMETRY=0
|
|
47
|
+
export DO_NOT_TRACK=1
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
On PowerShell:
|
|
51
|
+
|
|
52
|
+
```powershell
|
|
53
|
+
$env:LIFTOFF_TELEMETRY = "0"
|
|
54
|
+
$env:DO_NOT_TRACK = "1"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Telemetry is also disabled when `CI=true`. Disabled runs do not show the notice,
|
|
58
|
+
create telemetry state, or initialize network transport.
|
|
59
|
+
|
|
60
|
+
## Delivery and failure behavior
|
|
61
|
+
|
|
62
|
+
The CLI makes one HTTPS request after command completion with a maximum
|
|
63
|
+
one-second delivery budget. It does not retry, buffer, read a response body, or
|
|
64
|
+
report telemetry failures. Offline use, command output, JSON stdout, and the
|
|
65
|
+
original exit status remain unchanged when the service is unavailable.
|
|
66
|
+
|
|
67
|
+
## Azure processing and retention
|
|
68
|
+
|
|
69
|
+
The public endpoint is a strict-schema plain Node.js service in Azure Container
|
|
70
|
+
Apps. It counts streamed bytes before parsing, rejects unknown or additional
|
|
71
|
+
fields, and adds server-side `TimeGenerated`. A managed identity then writes only
|
|
72
|
+
these Liftoff-defined columns through an Azure Monitor data collection rule:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
TimeGenerated, EventName, SchemaVersion, Command, CliVersion, Outcome
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Azure Monitor adds standard workspace system columns after the data collection
|
|
79
|
+
rule transformation. Those platform columns contain tenant, type, item, and
|
|
80
|
+
billing metadata; they are not additional Liftoff event fields and are not
|
|
81
|
+
populated from the request body, source IP, or derived geolocation.
|
|
82
|
+
|
|
83
|
+
Azure networking necessarily handles the source network address while routing
|
|
84
|
+
HTTPS. Liftoff does not copy that address into the event, derive geolocation
|
|
85
|
+
from it, forward it to the data collection rule, or configure the product
|
|
86
|
+
workspace to persist Container Apps ingress or console telemetry. The Container
|
|
87
|
+
Apps environment has persistent platform logs disabled, and the gateway has no
|
|
88
|
+
Application Insights connection string or instrumentation key.
|
|
89
|
+
|
|
90
|
+
Accepted events are stored in `LiftoffCommandEvents_CL` in the operator-selected
|
|
91
|
+
Azure region for 180 days of analytics and total retention, with no additional
|
|
92
|
+
long-term retention. Query access uses Microsoft Entra ID and Azure RBAC.
|
|
93
|
+
Aggregate counts are directional because a public, unauthenticated endpoint can
|
|
94
|
+
receive forged events.
|
|
95
|
+
|
|
96
|
+
## Operator deployment boundary
|
|
97
|
+
|
|
98
|
+
Production telemetry resources are created and managed in the fixed resource
|
|
99
|
+
group `rg-liftoff-prod`. OpenTofu owns the group, applies deletion protection,
|
|
100
|
+
and deploys ACR Basic, a commit-pinned ACR build task, a Container Apps
|
|
101
|
+
environment, one warm Container App replica, managed identity, workspace,
|
|
102
|
+
custom table, data collection endpoint, and data collection rule.
|
|
103
|
+
|
|
104
|
+
The registry contains only the already-public gateway image. Administrator
|
|
105
|
+
credentials and anonymous pull are disabled; the Container App uses its
|
|
106
|
+
resource-scoped `AcrPull` identity. A full public Git commit SHA identifies the
|
|
107
|
+
build tag; the running Container App is pinned to the resolved `sha256` manifest
|
|
108
|
+
digest, never a branch, `latest`, or tag-only reference.
|
|
109
|
+
|
|
110
|
+
OpenTofu state storage remains in a separate enforced Azure Network Security
|
|
111
|
+
Perimeter. Its explicit operator IPv4 `/32` CIDRs live only in ignored local
|
|
112
|
+
inputs, and Entra authentication plus storage-scoped RBAC remain required. The
|
|
113
|
+
Container App needs no Function host/deployment storage, package blob, or Azure
|
|
114
|
+
Files share.
|
|
115
|
+
|
|
116
|
+
The gateway uses the smallest Container Apps Consumption allocation: 0.25 vCPU,
|
|
117
|
+
0.5 GiB, one minimum replica, and five maximum replicas. Keeping one replica
|
|
118
|
+
ready prevents scale-to-zero cold starts from consuming the client's one-second
|
|
119
|
+
delivery budget. It adds reduced idle compute cost plus ACR Basic cost.
|
|
120
|
+
|
|
121
|
+
From the repository root, operators build and validate with:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm ci --prefix services/telemetry-ingest
|
|
125
|
+
npm run check --prefix services/telemetry-ingest
|
|
126
|
+
npm run package --prefix services/telemetry-ingest
|
|
127
|
+
npm run smoke:container --prefix services/telemetry-ingest
|
|
128
|
+
tofu -chdir=infrastructure/opentofu/telemetry fmt -check
|
|
129
|
+
tofu -chdir=infrastructure/opentofu/telemetry init -backend=false
|
|
130
|
+
tofu -chdir=infrastructure/opentofu/telemetry validate
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Real environments must use access-controlled remote state and Entra
|
|
134
|
+
authentication. Before apply, review the subscription, region, unique resource
|
|
135
|
+
suffix, full public source revision, immutable image digest,
|
|
136
|
+
`rg-liftoff-prod` deletion protection, ACR administrator and anonymous-access
|
|
137
|
+
disablement, managed-identity roles, one-to-five replica bounds, disabled
|
|
138
|
+
persistent platform logs, six-column schema, 180-day retention, ingestion
|
|
139
|
+
quota, and state perimeter rules. Operator CIDRs live only in ignored local
|
|
140
|
+
inputs. If the operator IP changes, update and apply the bootstrap access rule
|
|
141
|
+
through the Azure control plane before retrying backend access. Use the same
|
|
142
|
+
reviewed production variable file for every plan, apply, and emergency
|
|
143
|
+
disablement so region, image revision, and quota inputs cannot fall back to
|
|
144
|
+
defaults.
|
|
145
|
+
Every infrastructure lifecycle action uses `tofu`; Liftoff does not use Bicep,
|
|
146
|
+
`azd`, Terraform CLI, or ad hoc Azure resource commands for this service.
|
|
147
|
+
|
|
148
|
+
Standard GitHub-hosted runners run static validation only. They do not plan or
|
|
149
|
+
apply production because their dynamic networks are not admitted to the
|
|
150
|
+
perimeter.
|
|
151
|
+
|
|
152
|
+
After apply, operators must verify the registry identity boundary, one ready
|
|
153
|
+
replica, sub-second endpoint response, synthetic allowlisted event, six
|
|
154
|
+
Liftoff-defined columns, expected Azure system columns, server time, retention,
|
|
155
|
+
and absence of request, IP, geolocation, Container Apps platform/console, or
|
|
156
|
+
Application Insights records before compiling the endpoint into a Liftoff
|
|
157
|
+
release.
|
|
158
|
+
|
|
159
|
+
The final production architecture contains no Function App, FC1 plan, product
|
|
160
|
+
storage, OneDeploy action, or production storage-perimeter association.
|
|
161
|
+
|
|
162
|
+
For emergency disablement, apply the OpenTofu configuration with
|
|
163
|
+
`ingestion_enabled=false`, then publish a patch with client delivery disabled.
|
|
164
|
+
Rollback preserves `rg-liftoff-prod`; do not destroy the protected production
|
|
165
|
+
resource group.
|
|
166
|
+
|
|
167
|
+
Normal `liftoff` commands never authenticate to Azure, read OpenTofu state, or
|
|
168
|
+
deploy telemetry infrastructure.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -67,15 +67,13 @@ hand-edited unsafe path.
|
|
|
67
67
|
|
|
68
68
|
## Update reports conflicts or orphans
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
-
|
|
76
|
-
|
|
77
|
-
- For prompt-free conflict replacement, use `liftoff update --apply --force`
|
|
78
|
-
only after reviewing every listed path.
|
|
70
|
+
`liftoff update` applies safe managed changes immediately and skips conflicts.
|
|
71
|
+
|
|
72
|
+
- Use `liftoff update --check` for a read-only human report or
|
|
73
|
+
`liftoff update --check --json` for an automation drift gate.
|
|
74
|
+
- Local or user-owned conflicts remain untouched by default.
|
|
75
|
+
- Use `liftoff update --force` only after reviewing every listed path and
|
|
76
|
+
deciding that each overwrite is intended.
|
|
79
77
|
- Orphans are never deleted automatically.
|
|
80
78
|
- Update reports dependency-definition impact but does not install
|
|
81
79
|
dependencies.
|
package/docs/workloads.md
CHANGED
|
@@ -126,3 +126,7 @@ created the application.
|
|
|
126
126
|
workload. It does not convert among GenAI, API, and Power Apps or change an API
|
|
127
127
|
stack, GenAI pattern, or user-supplied starter identity. Initialize a fresh
|
|
128
128
|
project or use a supported migration flow instead.
|
|
129
|
+
|
|
130
|
+
Plain update applies safe changes immediately for every workload. Use
|
|
131
|
+
`liftoff update --check` for read-only inspection and review all reported
|
|
132
|
+
conflicts before using `liftoff update --force`; orphans remain untouched.
|
package/package.json
CHANGED
package/dist/update-impact.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { ReconcileEntry } from './reconcile.js';
|
|
2
|
-
export declare const dependencyDefinitionLogicalNames: readonly ["backend-pyproject", "function-worker-requirements", "node-backend-package", "node-backend-lock", "go-backend-module", "go-backend-checksums", "frontend-package", "frontend-lock", "power-apps-package", "power-apps-lock"];
|
|
3
|
-
export interface UpdateImpact {
|
|
4
|
-
readonly creates: readonly string[];
|
|
5
|
-
readonly restores: readonly string[];
|
|
6
|
-
readonly replacements: readonly string[];
|
|
7
|
-
readonly moves: readonly string[];
|
|
8
|
-
readonly recordedStateRefreshes: readonly string[];
|
|
9
|
-
readonly conflicts: readonly string[];
|
|
10
|
-
readonly managedPathsRemoved: readonly string[];
|
|
11
|
-
readonly managedPathsRemovedOnOverwrite: readonly string[];
|
|
12
|
-
readonly orphansPreserved: readonly string[];
|
|
13
|
-
readonly dependencyDefinitions: readonly string[];
|
|
14
|
-
readonly safeActionCount: number;
|
|
15
|
-
readonly localOrUserOwnedFilesAtRisk: number;
|
|
16
|
-
readonly manifestWillUpdate: boolean;
|
|
17
|
-
readonly installsDependencies: false;
|
|
18
|
-
readonly deletesOrphans: false;
|
|
19
|
-
readonly retainsBackupAfterSuccess: false;
|
|
20
|
-
readonly hasSafeActions: boolean;
|
|
21
|
-
readonly hasActionableChanges: boolean;
|
|
22
|
-
}
|
|
23
|
-
export declare function buildUpdateImpact(entries: readonly ReconcileEntry[]): UpdateImpact;
|
package/dist/update-impact.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { manifestDisplayPath } from './file-system.js';
|
|
2
|
-
export const dependencyDefinitionLogicalNames = Object.freeze([
|
|
3
|
-
'backend-pyproject',
|
|
4
|
-
'function-worker-requirements',
|
|
5
|
-
'node-backend-package',
|
|
6
|
-
'node-backend-lock',
|
|
7
|
-
'go-backend-module',
|
|
8
|
-
'go-backend-checksums',
|
|
9
|
-
'frontend-package',
|
|
10
|
-
'frontend-lock',
|
|
11
|
-
'power-apps-package',
|
|
12
|
-
'power-apps-lock'
|
|
13
|
-
]);
|
|
14
|
-
const dependencyDefinitionLogicalNameSet = new Set(dependencyDefinitionLogicalNames);
|
|
15
|
-
function comparePortable(left, right) {
|
|
16
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
17
|
-
}
|
|
18
|
-
function displayEntry(entry) {
|
|
19
|
-
const current = manifestDisplayPath(entry.pathParts);
|
|
20
|
-
return entry.previousPathParts
|
|
21
|
-
? `${manifestDisplayPath(entry.previousPathParts)} => ${current}`
|
|
22
|
-
: current;
|
|
23
|
-
}
|
|
24
|
-
function freezeSorted(values) {
|
|
25
|
-
return Object.freeze(values.sort(comparePortable));
|
|
26
|
-
}
|
|
27
|
-
function isActionable(entry) {
|
|
28
|
-
return entry.status !== 'orphan' &&
|
|
29
|
-
(entry.status !== 'unchanged' || entry.refreshHash === true);
|
|
30
|
-
}
|
|
31
|
-
export function buildUpdateImpact(entries) {
|
|
32
|
-
const creates = [];
|
|
33
|
-
const restores = [];
|
|
34
|
-
const replacements = [];
|
|
35
|
-
const moves = [];
|
|
36
|
-
const recordedStateRefreshes = [];
|
|
37
|
-
const conflicts = [];
|
|
38
|
-
const managedPathsRemoved = [];
|
|
39
|
-
const managedPathsRemovedOnOverwrite = [];
|
|
40
|
-
const orphansPreserved = [];
|
|
41
|
-
const dependencyDefinitions = [];
|
|
42
|
-
for (const entry of entries) {
|
|
43
|
-
switch (entry.status) {
|
|
44
|
-
case 'new':
|
|
45
|
-
creates.push(manifestDisplayPath(entry.pathParts));
|
|
46
|
-
break;
|
|
47
|
-
case 'missing':
|
|
48
|
-
restores.push(manifestDisplayPath(entry.pathParts));
|
|
49
|
-
break;
|
|
50
|
-
case 'upgrade':
|
|
51
|
-
replacements.push(manifestDisplayPath(entry.pathParts));
|
|
52
|
-
break;
|
|
53
|
-
case 'moved':
|
|
54
|
-
if (entry.cleanMove) {
|
|
55
|
-
moves.push(displayEntry(entry));
|
|
56
|
-
if (entry.previousPathParts) {
|
|
57
|
-
managedPathsRemoved.push(manifestDisplayPath(entry.previousPathParts));
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
if (entry.sourceModified && entry.previousPathParts) {
|
|
62
|
-
conflicts.push(manifestDisplayPath(entry.previousPathParts));
|
|
63
|
-
}
|
|
64
|
-
if (entry.destinationOccupied && !entry.destinationMatches) {
|
|
65
|
-
conflicts.push(manifestDisplayPath(entry.pathParts));
|
|
66
|
-
}
|
|
67
|
-
if (entry.previousPathParts) {
|
|
68
|
-
managedPathsRemovedOnOverwrite.push(manifestDisplayPath(entry.previousPathParts));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
break;
|
|
72
|
-
case 'conflict':
|
|
73
|
-
conflicts.push(manifestDisplayPath(entry.pathParts));
|
|
74
|
-
break;
|
|
75
|
-
case 'orphan':
|
|
76
|
-
orphansPreserved.push(manifestDisplayPath(entry.pathParts));
|
|
77
|
-
break;
|
|
78
|
-
case 'unchanged':
|
|
79
|
-
if (entry.refreshHash) {
|
|
80
|
-
recordedStateRefreshes.push(manifestDisplayPath(entry.pathParts));
|
|
81
|
-
}
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
if (isActionable(entry) &&
|
|
85
|
-
dependencyDefinitionLogicalNameSet.has(entry.logicalName)) {
|
|
86
|
-
dependencyDefinitions.push(manifestDisplayPath(entry.pathParts));
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
const frozenCreates = freezeSorted(creates);
|
|
90
|
-
const frozenRestores = freezeSorted(restores);
|
|
91
|
-
const frozenReplacements = freezeSorted(replacements);
|
|
92
|
-
const frozenMoves = freezeSorted(moves);
|
|
93
|
-
const frozenRefreshes = freezeSorted(recordedStateRefreshes);
|
|
94
|
-
const frozenConflicts = freezeSorted(conflicts);
|
|
95
|
-
const frozenManagedPaths = freezeSorted(managedPathsRemoved);
|
|
96
|
-
const frozenManagedOverwritePaths = freezeSorted(managedPathsRemovedOnOverwrite);
|
|
97
|
-
const frozenOrphans = freezeSorted(orphansPreserved);
|
|
98
|
-
const frozenDependencyDefinitions = freezeSorted(dependencyDefinitions);
|
|
99
|
-
const safeActionCount = frozenCreates.length +
|
|
100
|
-
frozenRestores.length +
|
|
101
|
-
frozenReplacements.length +
|
|
102
|
-
frozenMoves.length +
|
|
103
|
-
frozenRefreshes.length;
|
|
104
|
-
const hasSafeActions = safeActionCount > 0;
|
|
105
|
-
const hasActionableChanges = hasSafeActions || frozenConflicts.length > 0;
|
|
106
|
-
return Object.freeze({
|
|
107
|
-
creates: frozenCreates,
|
|
108
|
-
restores: frozenRestores,
|
|
109
|
-
replacements: frozenReplacements,
|
|
110
|
-
moves: frozenMoves,
|
|
111
|
-
recordedStateRefreshes: frozenRefreshes,
|
|
112
|
-
conflicts: frozenConflicts,
|
|
113
|
-
managedPathsRemoved: frozenManagedPaths,
|
|
114
|
-
managedPathsRemovedOnOverwrite: frozenManagedOverwritePaths,
|
|
115
|
-
orphansPreserved: frozenOrphans,
|
|
116
|
-
dependencyDefinitions: frozenDependencyDefinitions,
|
|
117
|
-
safeActionCount,
|
|
118
|
-
localOrUserOwnedFilesAtRisk: frozenConflicts.length,
|
|
119
|
-
manifestWillUpdate: hasActionableChanges,
|
|
120
|
-
installsDependencies: false,
|
|
121
|
-
deletesOrphans: false,
|
|
122
|
-
retainsBackupAfterSuccess: false,
|
|
123
|
-
hasSafeActions,
|
|
124
|
-
hasActionableChanges
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
//# sourceMappingURL=update-impact.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"update-impact.js","sourceRoot":"","sources":["../src/update-impact.ts"],"names":[],"mappings":"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"}
|