@knpkv/alchemy-console 0.4.2 → 0.5.1
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 +117 -15
- package/dist/api.d.ts +87 -16
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +7 -0
- package/dist/api.js.map +1 -1
- package/dist/client/assets/{index-CHwWf6VU.css → index-D5bP19PT.css} +1 -1
- package/dist/client/assets/index-D9T2ytki.js +58 -0
- package/dist/client/index.html +2 -2
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/plan.d.ts +109 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +40 -0
- package/dist/plan.js.map +1 -0
- package/dist/presentation/PlanView.d.ts +10 -0
- package/dist/presentation/PlanView.d.ts.map +1 -0
- package/dist/presentation/PlanView.js +70 -0
- package/dist/presentation/PlanView.js.map +1 -0
- package/dist/presentation/StackDetailView.d.ts +4 -1
- package/dist/presentation/StackDetailView.d.ts.map +1 -1
- package/dist/presentation/StackDetailView.js +9 -3
- package/dist/presentation/StackDetailView.js.map +1 -1
- package/dist/presentation/detail-model.d.ts +1 -1
- package/dist/presentation/detail-model.d.ts.map +1 -1
- package/dist/server/Catalog.d.ts +1 -0
- package/dist/server/Catalog.d.ts.map +1 -1
- package/dist/server/Catalog.js +7 -1
- package/dist/server/Catalog.js.map +1 -1
- package/dist/server/HttpApplication.d.ts +2 -1
- package/dist/server/HttpApplication.d.ts.map +1 -1
- package/dist/server/HttpApplication.js +3 -1
- package/dist/server/HttpApplication.js.map +1 -1
- package/dist/server/Launch.d.ts +1 -1
- package/dist/server/Launch.d.ts.map +1 -1
- package/dist/server/PlanReader.d.ts +19 -0
- package/dist/server/PlanReader.d.ts.map +1 -0
- package/dist/server/PlanReader.js +202 -0
- package/dist/server/PlanReader.js.map +1 -0
- package/dist/server/Server.d.ts +1 -1
- package/dist/server/Server.d.ts.map +1 -1
- package/dist/server/plan/archive.d.ts +10 -0
- package/dist/server/plan/archive.d.ts.map +1 -0
- package/dist/server/plan/archive.js +62 -0
- package/dist/server/plan/archive.js.map +1 -0
- package/dist/server/plan/github.d.ts +106 -0
- package/dist/server/plan/github.d.ts.map +1 -0
- package/dist/server/plan/github.js +157 -0
- package/dist/server/plan/github.js.map +1 -0
- package/dist/server/plan/receipt.d.ts +153 -0
- package/dist/server/plan/receipt.d.ts.map +1 -0
- package/dist/server/plan/receipt.js +112 -0
- package/dist/server/plan/receipt.js.map +1 -0
- package/dist/views/index.js +547 -264
- package/dist/views/style.css +1 -1
- package/dist/views.d.ts +3 -0
- package/dist/views.d.ts.map +1 -1
- package/dist/views.js +1 -0
- package/dist/views.js.map +1 -1
- package/package.json +3 -3
- package/dist/client/assets/index-DbklFcSg.js +0 -58
package/README.md
CHANGED
|
@@ -12,23 +12,24 @@ The browser shows stacks grouped by app, with desktop columns and compact phone
|
|
|
12
12
|
rows. Read again starts a fresh discovery request and clears the previous rows.
|
|
13
13
|
Loading, empty, incomplete discovery and owner sign-in failures are explicit.
|
|
14
14
|
Missing metadata reads Unknown; zero resources remains zero. No polling, cached
|
|
15
|
-
rows, plan, apply or destroy runs. Stage names and known resource counts open the
|
|
15
|
+
rows, local plan, apply or destroy runs. Stage names and known resource counts open the
|
|
16
16
|
stack UI. Resources lists actual returned resource metadata; State groups the
|
|
17
17
|
same resources by their returned construct parent and exact type. Resource rows
|
|
18
18
|
open identity and dependency details. Outputs distinguishes Hidden values, proven
|
|
19
|
-
empty state and unavailable formats.
|
|
20
|
-
changes action is present.
|
|
19
|
+
empty state and unavailable formats. Plan shows the latest plan infrastructure CI already published. No raw JSON or
|
|
20
|
+
Preview changes action is present.
|
|
21
21
|
|
|
22
22
|
The standalone wrapper shows Alchemy console, the actual local listener address
|
|
23
23
|
and owner session status. It adds no Relay host inventory or shell navigation.
|
|
24
24
|
|
|
25
25
|
Configuration is read at startup:
|
|
26
26
|
|
|
27
|
-
| Variable
|
|
28
|
-
|
|
|
29
|
-
| `ALCHEMY_CONSOLE_ROOT`
|
|
30
|
-
| `AWS_CONFIG_FILE`
|
|
31
|
-
| `ALCHEMY_CONSOLE_HOME`
|
|
27
|
+
| Variable | Default | Boundary |
|
|
28
|
+
| -------------------------- | ---------------------------------------------- | -------------------------------------- |
|
|
29
|
+
| `ALCHEMY_CONSOLE_ROOT` | `Work/dev` under the user's home | Server-private project discovery path |
|
|
30
|
+
| `AWS_CONFIG_FILE` | `.aws/config` under the user's home | Server-private SSO configuration path |
|
|
31
|
+
| `ALCHEMY_CONSOLE_HOME` | `.cache/alchemy-console` under the user's home | Server-private control directory |
|
|
32
|
+
| `ALCHEMY_CONSOLE_CI_TOKEN` | Unconfigured | Server-private read-only Actions token |
|
|
32
33
|
|
|
33
34
|
Login reuse is per port. A reused server keeps its startup configuration. The
|
|
34
35
|
control directory must be owned by the current user with mode `0700`; each
|
|
@@ -40,7 +41,7 @@ POSIX ownership and Unix sockets.
|
|
|
40
41
|
## Authenticated API
|
|
41
42
|
|
|
42
43
|
The client-safe contracts are exported from `@knpkv/alchemy-console/api` and may be
|
|
43
|
-
used with Effect's `HttpApiClient`.
|
|
44
|
+
used with Effect's `HttpApiClient`. All endpoints require the process's owner
|
|
44
45
|
cookie, and all responses are private and uncacheable:
|
|
45
46
|
|
|
46
47
|
The cookie name includes the bound listener port, so sessions on different ports
|
|
@@ -49,10 +50,11 @@ Cookies still share the loopback host and travel across ports; the name separate
|
|
|
49
50
|
sessions and does not provide port confidentiality. The API middleware resolves
|
|
50
51
|
the name at runtime rather than declaring a fixed OpenAPI cookie scheme.
|
|
51
52
|
|
|
52
|
-
| Route
|
|
53
|
-
|
|
|
54
|
-
| `GET /api/stacks`
|
|
55
|
-
| `GET /api/stacks/:id`
|
|
53
|
+
| Route | Result |
|
|
54
|
+
| -------------------------- | -------------------------------------------------------- |
|
|
55
|
+
| `GET /api/stacks` | Stack summaries and explicit local/S3 discovery issues |
|
|
56
|
+
| `GET /api/stacks/:id` | Current normalized resource state for a listed stack |
|
|
57
|
+
| `GET /api/stacks/:id/plan` | Latest verified CI plan or an explicit unavailable state |
|
|
56
58
|
|
|
57
59
|
Listing runs discovery on demand, without polling or schedules. IDs are random,
|
|
58
60
|
process-scoped identifiers with no encoded locator. They remain stable across
|
|
@@ -78,16 +80,116 @@ remain in the server and HttpOnly cookie. Every unsafe API method is refused,
|
|
|
78
80
|
including apply and destroy. Reads reject foreign origins and cross-site browser
|
|
79
81
|
requests. Listener and request Host are restricted to the bound loopback address.
|
|
80
82
|
|
|
83
|
+
## CI plans
|
|
84
|
+
|
|
85
|
+
The console never imports or executes stack code. It reads the `plan.json`
|
|
86
|
+
publication from infrastructure CI in `knpkv/infra`. Only `site/prod` and
|
|
87
|
+
`aws-org/org` map to that repository's `site` and `aws-org` stacks. Other app/stage
|
|
88
|
+
pairs show Not connected.
|
|
89
|
+
|
|
90
|
+
Set `ALCHEMY_CONSOLE_CI_TOKEN` on the server to a dedicated fine-grained token with
|
|
91
|
+
Actions read access to that repository. The token is held in redacted server
|
|
92
|
+
configuration; no host `gh` token is discovered. The current main comparison uses
|
|
93
|
+
the newest main push workflow run's SHA, the latest main commit seen by CI.
|
|
94
|
+
It does not query Git references or require Contents access. If no main push run
|
|
95
|
+
is visible, only the age rule applies. This comparison does not prove the current
|
|
96
|
+
Git branch tip.
|
|
97
|
+
|
|
98
|
+
The reader selects the newest non-expired matching artifact and verifies the
|
|
99
|
+
receipt and provenance inputs listed below. Both archive and expanded
|
|
100
|
+
JSON must be below 1 MB. API metadata has a separate 2 MiB per-response cap to
|
|
101
|
+
accommodate full 100-row pages before schema projection. Metadata pagination stops
|
|
102
|
+
at ten pages and the whole read has a 30-second timeout. ZIP inspection and decompression stay in memory. No
|
|
103
|
+
payload is logged or extracted to disk.
|
|
104
|
+
|
|
105
|
+
A publication becomes stale after 24 hours or when its base differs from the
|
|
106
|
+
latest main commit seen by CI. A newer failed stack run can retain the verified
|
|
107
|
+
last publication with a stale notice. The latest attempt must have run the selected
|
|
108
|
+
stack’s `Native read-only plan` step. Attempts are ordered by `run_started_at`,
|
|
109
|
+
then run ID and attempt number, descending; `updated_at` does not decide order.
|
|
110
|
+
A successful job that skipped that step, or
|
|
111
|
+
a newer attempt for another stack, does not replace the selected stack’s attempt. Expired, unverified, unconnected and
|
|
112
|
+
unavailable states have no rows. Infra CI not publishing is distinct from a
|
|
113
|
+
stack's first publication. Only a CI transport failure offers Retry, which reads
|
|
114
|
+
again and never executes a plan. Owner-session failures return to the console's
|
|
115
|
+
sign-in/error state instead of pretending CI refused access.
|
|
116
|
+
Fixed repository/workflow discovery returning 404 is treated as refused CI access;
|
|
117
|
+
the response cannot distinguish denied access from a removed configured workflow.
|
|
118
|
+
Missing individual runs/artifacts and HTTP 429/5xx remain retryable transport failures.
|
|
119
|
+
|
|
120
|
+
### Canonical receipt and identity boundaries
|
|
121
|
+
|
|
122
|
+
The persisted representation is the UTF-8 JSON receipt in the single regular
|
|
123
|
+
`plan.json` ZIP member of an Actions artifact named `infra-plan-<stack>-<head>`.
|
|
124
|
+
The server reads the artifact from the private `knpkv/infra` repository; that
|
|
125
|
+
repository name also appears in authenticated-client run URLs. Its entire
|
|
126
|
+
downloaded ZIP byte sequence is SHA-256 hashed and compared with the Actions
|
|
127
|
+
artifact's `sha256:<hex>` digest before decompression and exact-key receipt decoding.
|
|
128
|
+
|
|
129
|
+
Only `native.semantic` uses canonical semantic hashing: recursively sort object
|
|
130
|
+
keys, preserve array order, serialize with compact `JSON.stringify`, encode UTF-8,
|
|
131
|
+
then SHA-256 to lowercase hex and compare with `native.digest`. This is not a hash
|
|
132
|
+
of the whole receipt. The surrounding receipt identities are protected by the ZIP
|
|
133
|
+
digest and the separate provenance checks in this table.
|
|
134
|
+
|
|
135
|
+
| Input | Binding or validation | Boundary |
|
|
136
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
137
|
+
| Repository IDs | Producer/publisher `repository.id` and `head_repository.id`, artifact `workflow_run.repository_id` and `head_repository_id`, and main-CI repository IDs must equal `1288997422`. | Server-private API coordinates and pins. |
|
|
138
|
+
| Workflow identities | Active workflow definitions have exact paths `.github/workflows/infra.yml` and `.github/workflows/infra-publish.yml`; run `workflow_id` must match the respective definition ID. Run paths require the exact filename, with an optional validated `@ref`. Publisher refs are main; producer refs may also match its head branch or a recorded PR merge ref. | Server-private IDs, paths and refs. |
|
|
139
|
+
| Actor identities | Both producer/publisher `actor.id` and `triggering_actor.id` must equal `833092`. | Server-private numeric pins; no actor names are projected. |
|
|
140
|
+
| Producer run | Receipt `producerRunId` retrieves the run; its `id`, event `pull_request`, completed/success state, positive `run_attempt` and `run_started_at` identify the current reported attempt. Start time orders attempts; it is not a semantic-hash input. | Run ID can cross only within an allowlisted failed-run URL; attempt/start metadata remains server-private. |
|
|
141
|
+
| Producer job and step | Exactly one `<stack> / native` job must match the run's attempt and complete successfully; exactly one `Native read-only plan` step must have started and completed successfully. Job `id` is a positive API identity, not a receipt-pinned value. Schema 1 persists neither producer job ID nor producer attempt number. | Server-private job/attempt/step metadata. |
|
|
142
|
+
| Publisher run | Artifact `workflow_run.id` selects the run lookup; receipt `runId` equals the fetched run ID. Event is `workflow_run`, branch is `main`, state is completed/success, and `head_sha` equals both receipt `base` and artifact `workflow_run.head_sha`. | Run ID crosses within the allowlisted publication URL; branch/event/status and attempt metadata remain server-private. |
|
|
143
|
+
| Publisher job/attempt | Receipt `publisherJobId` equals a successful completed `<stack> / publish` job's immutable `id`; its `run_attempt` equals the current publisher attempt. Attempt number is API metadata, not a separate persisted receipt field. | Server-private job ID and attempt. |
|
|
144
|
+
| Publication artifact | API artifact `id` selects the download; `name` supplies the full head suffix bound to receipt `head`. `workflow_run.head_branch` must be `main`; run ID/SHA bind through the publisher row. Download length equals `size_in_bytes`; SHA-256 equals `digest`. `expired` and `expires_at` govern selection; `created_at` supplies publication age, not attempt order. | Artifact IDs, name, full digest and expiry metadata remain server-private. Only normalized `publishedAt` / `ageDays` cross owner HTTP. |
|
|
145
|
+
| PR/revisions | Receipt `pr`, `head`, `base` match the producer's `pull_requests[].number`, `head.sha`, `base.sha`; producer `head_sha` also equals receipt `head`. | Authenticated client sees PR number and seven-character head/base SHAs. Full revisions remain server-private. |
|
|
146
|
+
| Referenced workflow | Producer `referenced_workflows` must contain path `knpkv/infra/.github/workflows/_infra-plan.yml@main` or `@refs/heads/main`, ref `refs/heads/main`, and SHA equal to receipt `base`. | Server-private path/ref/full SHA; only the short base projection crosses. |
|
|
147
|
+
| Tools | Receipt `toolsSha` equals `base`; `toolsDigest` must be a 64-character lowercase hex hash. The console does not independently recompute `toolsDigest`. | Server-private tool identity/hash; only the separate short base projection crosses. |
|
|
148
|
+
| Raw artifact descriptor | Receipt `rawArtifactId` is positive; `rawArtifactDigest` has `sha256:<64 lowercase hex>` shape. The console does not fetch or rehash this raw artifact. These are not the publication artifact's ID/digest above. | Server-private descriptor, never an owner HTTP field. |
|
|
149
|
+
| Receipt assurance | `assurance` equals `untrusted-native-data/trusted-publication`. | Server-private receipt marker. |
|
|
150
|
+
| Schemas/stack/stage | Receipt `schema` and `native.schema` equal `1`. Receipt `stack`, `native.stack` and `native.semantic.stack` equal the selected mapped stack. Native/semantic stages agree: `site/prod` uses semantic schema `alchemy-beta77/ci-native-v1`; `aws-org/org` uses `alchemy-beta81/ci-native-v1`. `native.statePuts` equals `0`. | Schema/assurance markers stay server-private. Selected app/stage already cross as authenticated stack metadata. |
|
|
151
|
+
| Semantic impact | `native.semantic.impact` contains the selected stack, has one or two allowed stack names and no duplicates. | Server-private semantic-hash input. |
|
|
152
|
+
| Semantic resource identities | `native.semantic.rows[].fqn` / `type` exactly match the unique pins: `Site` → `Cloudflare.Worker`; `Platform`, `Sandbox` → `AWS.Organizations.OrganizationalUnit`; `Dev1Placement`, `DevPlacement`, `Dev2Placement`, `InfraPlacement` → `Org.AccountPlacement`. Site has one row; organization has six. | These semantic-hash inputs cross owner HTTP as normalized `fqn` / `resourceType`. |
|
|
153
|
+
| Semantic actions | `native.semantic.rows[].action` is `noop` or `update`; `native.hasChanges` agrees with the presence of an update. | Action crosses owner HTTP; the receipt boolean remains server-private. |
|
|
154
|
+
| Semantic property names | `native.semantic.rows[].changedKeys` has at most 32 names matching `^[A-Za-z][A-Za-z0-9_.-]{0,63}$`. | Names cross owner HTTP. Property values do not. |
|
|
155
|
+
| Semantic value hashes/mode | `native.semantic.rows[].props`, `attr`, `bindings` are lowercase 64-character hex hashes; `mode` is `live`. | Server-private semantic-hash inputs; no original values are stored in this receipt. |
|
|
156
|
+
| Semantic content/build/output | `native.semantic.contentDigest`, `output`, site `artifacts["Site/build"]` and `assetHashes.Site` are lowercase 64-character hex hashes. Organization `artifacts` is empty and has no `assetHashes` field. All are included in semantic hashing. | Server-private hashes/build keys; never projected or independently recomputed by this reader. |
|
|
157
|
+
| Semantic digest | `native.digest` equals the recomputed canonical semantic SHA-256. | Full digest remains server-private; only its first/last four hex characters cross owner HTTP. |
|
|
158
|
+
| Latest main commit seen by CI | The newest main push run must have the pinned repository IDs, `head_branch: main`, `event: push` and a valid `head_sha`. That SHA is compared with receipt `base` only for staleness. | Server-private comparison input; only normalized `stale: base` crosses. |
|
|
159
|
+
|
|
160
|
+
Every canonical semantic field above, including its schema/stack/stage, participates
|
|
161
|
+
in the semantic hash. Run/job/artifact metadata and surrounding receipt fields do
|
|
162
|
+
not. A valid ZIP digest authenticates receipt bytes against Actions metadata; it
|
|
163
|
+
does not strengthen shape-only fields into independently verified identities.
|
|
164
|
+
Tokens, signed download URLs, raw provider secrets and backend locators are never
|
|
165
|
+
durable receipt fields. Tokens and download URLs stay in the server transport.
|
|
166
|
+
|
|
167
|
+
The normalized authenticated client-visible projection contains PR number, short
|
|
168
|
+
head/base SHAs, publication time, safe GitHub run link, short semantic digest,
|
|
169
|
+
resource identity/type/action and bounded property names. These fields may cross
|
|
170
|
+
owner HTTP, but must not enter public or unauthenticated routes, browser storage
|
|
171
|
+
or telemetry. The token, signed artifact URLs, artifact/job IDs, full receipt
|
|
172
|
+
hashes, raw ZIP and unprojected semantic hash inputs remain server-private. Property values,
|
|
173
|
+
provider credentials and backend locators never enter this projection.
|
|
174
|
+
|
|
175
|
+
CI publication authenticates the source of the data, not the behavior of PR code.
|
|
176
|
+
The console does not certify CI's no-write or secret-access policy. No real CI
|
|
177
|
+
artifact is used by this feature's tests; all reader and browser states use
|
|
178
|
+
synthetic fixtures.
|
|
179
|
+
|
|
81
180
|
## Browser views
|
|
82
181
|
|
|
83
|
-
Import `StackListView`, `StackDetailView` and `ResourceDetailView` from `@knpkv/alchemy-console/views` and its stylesheet from
|
|
182
|
+
Import `StackListView`, `StackDetailView`, `PlanView` and `ResourceDetailView` from `@knpkv/alchemy-console/views` and its stylesheet from
|
|
84
183
|
`@knpkv/alchemy-console/views/style.css`. Mount them inside a Rly style/theme boundary.
|
|
85
184
|
Views consumers supply the optional React, React DOM and Rly peers; the standalone
|
|
86
185
|
browser shell already bundles them.
|
|
87
186
|
The application supplies normalized presentation data, a product label, host
|
|
88
187
|
sign-in instruction, read actions and real UI destinations. `StackListView` accepts
|
|
89
188
|
optional `stackHref`; without a destination, stages and counts remain text.
|
|
90
|
-
`StackDetailView` has controlled Resources/Outputs/State tabs and `resourceHref`.
|
|
189
|
+
`StackDetailView` has controlled Resources/Outputs/State/Plan tabs and `resourceHref`. Supply
|
|
190
|
+
`planState` and `onReadPlanAgain` for CI reading; without `planState`, Plan shows
|
|
191
|
+
Not connected. `PlanView` accepts the same controlled state and a read-only
|
|
192
|
+
`onReadAgain` callback.
|
|
91
193
|
`ResourceDetailView` accepts `stackHref` and `resourceHref`. Views fetch nothing,
|
|
92
194
|
read no configuration and persist no data. The standalone detail wrapper adds
|
|
93
195
|
breadcrumbs and Read again outside the referenced module content. Phone list
|
package/dist/api.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Client-safe contracts. IDs and metadata cross only the authenticated owner API, never public telemetry. */
|
|
2
2
|
import { Schema } from "effect";
|
|
3
3
|
import { HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware } from "effect/http-api";
|
|
4
|
+
export { PlanRow, PlanSource, PlanState, PublishedPlan } from "./plan.js";
|
|
4
5
|
/** Random, process-scoped identity; contains no encoded provider locator. Not persisted by the server. */
|
|
5
6
|
export declare const StackId: Schema.String;
|
|
6
7
|
export type StackId = typeof StackId.Type;
|
|
@@ -90,21 +91,7 @@ declare const OwnerAuth_base: HttpApiMiddleware.ServiceClass<OwnerAuth, "@knpkv/
|
|
|
90
91
|
/** The server resolves its listener-specific cookie name at request time. */
|
|
91
92
|
export declare class OwnerAuth extends OwnerAuth_base {
|
|
92
93
|
}
|
|
93
|
-
declare const AlchemyConsoleApi_base: HttpApi.HttpApi<"AlchemyConsoleApi", HttpApiGroup.HttpApiGroup<"stacks", HttpApiEndpoint.HttpApiEndpoint<"
|
|
94
|
-
readonly stacks: Schema.$Array<Schema.Struct<{
|
|
95
|
-
readonly id: Schema.String;
|
|
96
|
-
readonly app: Schema.NonEmptyString;
|
|
97
|
-
readonly stage: Schema.NonEmptyString;
|
|
98
|
-
readonly backend: Schema.Literals<readonly ["local", "s3"]>;
|
|
99
|
-
readonly alchemyVersion: Schema.NullOr<Schema.String>;
|
|
100
|
-
readonly lastDeploy: Schema.NullOr<Schema.String>;
|
|
101
|
-
readonly resourceCount: Schema.NullOr<Schema.Int>;
|
|
102
|
-
}>>;
|
|
103
|
-
readonly issues: Schema.$Array<Schema.Struct<{
|
|
104
|
-
readonly source: Schema.Literals<readonly ["local", "s3"]>;
|
|
105
|
-
readonly reason: Schema.Literals<readonly ["io", "invalid-state", "invalid-lockfile", "unsupported-version", "limit", "outside-root", "invalid-config", "authentication", "denied", "not-found", "provider", "invalid-response", "invalid-source"]>;
|
|
106
|
-
}>>;
|
|
107
|
-
}>>, Schema.toCodecJson<typeof CatalogReadError>, OwnerAuth, never> | HttpApiEndpoint.HttpApiEndpoint<"get", "GET", "/api/stacks/:id", Schema.toCodecStringTree<Schema.Struct<{
|
|
94
|
+
declare const AlchemyConsoleApi_base: HttpApi.HttpApi<"AlchemyConsoleApi", HttpApiGroup.HttpApiGroup<"stacks", HttpApiEndpoint.HttpApiEndpoint<"get", "GET", "/api/stacks/:id", Schema.toCodecStringTree<Schema.Struct<{
|
|
108
95
|
readonly id: Schema.String;
|
|
109
96
|
}>>, never, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
110
97
|
readonly id: Schema.String;
|
|
@@ -133,8 +120,92 @@ declare const AlchemyConsoleApi_base: HttpApi.HttpApi<"AlchemyConsoleApi", HttpA
|
|
|
133
120
|
readonly description: Schema.Null;
|
|
134
121
|
}>>>;
|
|
135
122
|
}>;
|
|
123
|
+
}>>, Schema.toCodecJson<typeof CatalogReadError | typeof StackNotFound>, OwnerAuth, never> | HttpApiEndpoint.HttpApiEndpoint<"list", "GET", "/api/stacks", never, never, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
124
|
+
readonly stacks: Schema.$Array<Schema.Struct<{
|
|
125
|
+
readonly id: Schema.String;
|
|
126
|
+
readonly app: Schema.NonEmptyString;
|
|
127
|
+
readonly stage: Schema.NonEmptyString;
|
|
128
|
+
readonly backend: Schema.Literals<readonly ["local", "s3"]>;
|
|
129
|
+
readonly alchemyVersion: Schema.NullOr<Schema.String>;
|
|
130
|
+
readonly lastDeploy: Schema.NullOr<Schema.String>;
|
|
131
|
+
readonly resourceCount: Schema.NullOr<Schema.Int>;
|
|
132
|
+
}>>;
|
|
133
|
+
readonly issues: Schema.$Array<Schema.Struct<{
|
|
134
|
+
readonly source: Schema.Literals<readonly ["local", "s3"]>;
|
|
135
|
+
readonly reason: Schema.Literals<readonly ["io", "invalid-state", "invalid-lockfile", "unsupported-version", "limit", "outside-root", "invalid-config", "authentication", "denied", "not-found", "provider", "invalid-response", "invalid-source"]>;
|
|
136
|
+
}>>;
|
|
137
|
+
}>>, Schema.toCodecJson<typeof CatalogReadError>, OwnerAuth, never> | HttpApiEndpoint.HttpApiEndpoint<"plan", "GET", "/api/stacks/:id/plan", Schema.toCodecStringTree<Schema.Struct<{
|
|
138
|
+
readonly id: Schema.String;
|
|
139
|
+
}>>, never, never, never, Schema.toCodecJson<Schema.TaggedUnion<{
|
|
140
|
+
readonly Expired: Schema.TaggedStruct<"Expired", {
|
|
141
|
+
readonly source: Schema.NullOr<Schema.Struct<{
|
|
142
|
+
readonly pr: Schema.NullOr<Schema.Int>;
|
|
143
|
+
readonly head: Schema.String;
|
|
144
|
+
readonly base: Schema.NullOr<Schema.String>;
|
|
145
|
+
readonly publishedAt: Schema.String;
|
|
146
|
+
readonly ageDays: Schema.Int;
|
|
147
|
+
readonly runHref: Schema.String;
|
|
148
|
+
}>>;
|
|
149
|
+
}>;
|
|
150
|
+
readonly Failed: Schema.TaggedStruct<"Failed", {
|
|
151
|
+
readonly runHref: Schema.String;
|
|
152
|
+
readonly lastPublished: Schema.NullOr<Schema.Struct<{
|
|
153
|
+
readonly source: Schema.Struct<{
|
|
154
|
+
readonly pr: Schema.NullOr<Schema.Int>;
|
|
155
|
+
readonly head: Schema.String;
|
|
156
|
+
readonly base: Schema.NullOr<Schema.String>;
|
|
157
|
+
readonly publishedAt: Schema.String;
|
|
158
|
+
readonly ageDays: Schema.Int;
|
|
159
|
+
readonly runHref: Schema.String;
|
|
160
|
+
}>;
|
|
161
|
+
readonly digest: Schema.String;
|
|
162
|
+
readonly rows: Schema.$Array<Schema.Struct<{
|
|
163
|
+
readonly fqn: Schema.NonEmptyString;
|
|
164
|
+
readonly resourceType: Schema.NonEmptyString;
|
|
165
|
+
readonly action: Schema.Literals<readonly ["noop", "update"]>;
|
|
166
|
+
readonly changedKeys: Schema.$Array<Schema.String>;
|
|
167
|
+
}>>;
|
|
168
|
+
readonly stale: Schema.NullOr<Schema.Literals<readonly ["age", "base", "failed"]>>;
|
|
169
|
+
}>>;
|
|
170
|
+
}>;
|
|
171
|
+
readonly Loading: Schema.TaggedStruct<"Loading", {}>;
|
|
172
|
+
readonly NotConnected: Schema.TaggedStruct<"NotConnected", {}>;
|
|
173
|
+
readonly NotPublished: Schema.TaggedStruct<"NotPublished", {}>;
|
|
174
|
+
readonly NotPublishing: Schema.TaggedStruct<"NotPublishing", {}>;
|
|
175
|
+
readonly Ready: Schema.TaggedStruct<"Ready", {
|
|
176
|
+
readonly plan: Schema.Struct<{
|
|
177
|
+
readonly source: Schema.Struct<{
|
|
178
|
+
readonly pr: Schema.NullOr<Schema.Int>;
|
|
179
|
+
readonly head: Schema.String;
|
|
180
|
+
readonly base: Schema.NullOr<Schema.String>;
|
|
181
|
+
readonly publishedAt: Schema.String;
|
|
182
|
+
readonly ageDays: Schema.Int;
|
|
183
|
+
readonly runHref: Schema.String;
|
|
184
|
+
}>;
|
|
185
|
+
readonly digest: Schema.String;
|
|
186
|
+
readonly rows: Schema.$Array<Schema.Struct<{
|
|
187
|
+
readonly fqn: Schema.NonEmptyString;
|
|
188
|
+
readonly resourceType: Schema.NonEmptyString;
|
|
189
|
+
readonly action: Schema.Literals<readonly ["noop", "update"]>;
|
|
190
|
+
readonly changedKeys: Schema.$Array<Schema.String>;
|
|
191
|
+
}>>;
|
|
192
|
+
readonly stale: Schema.NullOr<Schema.Literals<readonly ["age", "base", "failed"]>>;
|
|
193
|
+
}>;
|
|
194
|
+
}>;
|
|
195
|
+
readonly Refused: Schema.TaggedStruct<"Refused", {}>;
|
|
196
|
+
readonly Unreachable: Schema.TaggedStruct<"Unreachable", {}>;
|
|
197
|
+
readonly Unverified: Schema.TaggedStruct<"Unverified", {
|
|
198
|
+
readonly reason: Schema.Literals<readonly ["metadata", "provenance", "archive", "digest", "receipt"]>;
|
|
199
|
+
readonly source: Schema.NullOr<Schema.Struct<{
|
|
200
|
+
readonly pr: Schema.NullOr<Schema.Int>;
|
|
201
|
+
readonly head: Schema.String;
|
|
202
|
+
readonly base: Schema.NullOr<Schema.String>;
|
|
203
|
+
readonly publishedAt: Schema.String;
|
|
204
|
+
readonly ageDays: Schema.Int;
|
|
205
|
+
readonly runHref: Schema.String;
|
|
206
|
+
}>>;
|
|
207
|
+
}>;
|
|
136
208
|
}>>, Schema.toCodecJson<typeof CatalogReadError | typeof StackNotFound>, OwnerAuth, never>, false>>;
|
|
137
209
|
export declare class AlchemyConsoleApi extends AlchemyConsoleApi_base {
|
|
138
210
|
}
|
|
139
|
-
export {};
|
|
140
211
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,8GAA8G;AAC9G,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,8GAA8G;AAC9G,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAI3F,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAEzE,0GAA0G;AAC1G,eAAO,MAAM,OAAO,eAAuC,CAAA;AAC3D,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC,eAAO,MAAM,mBAAmB,oOAc9B,CAAA;AAEF,eAAO,MAAM,cAAc;;;EAGzB,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;AAEvD,eAAO,MAAM,YAAY;;;;;;;;EAQvB,CAAA;AACF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAEnD,eAAO,MAAM,SAAS;;;;;;;;;;;;;;EAA8F,CAAA;AACpH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC,IAAI,CAAA;AAC7C,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAoD,CAAA;AAC5E,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;;;;AAEjD,qBAAa,gBAAiB,SAAQ,qBAEZ;CAAG;;AAE7B,qBAAa,aAAc,SAAQ,kBAAgF;CAAG;;AAEtH,qBAAa,YAAa,SAAQ,iBAA8E;CAAG;;AAEnH,qBAAa,SAAU,SAAQ,cAAwE;CAAG;;;;;;;;;AAE1G,6EAA6E;AAC7E,qBAAa,SAAU,SAAQ,cAE7B;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBL,qBAAa,iBAAkB,SAAQ,sBAAmE;CAAG"}
|
package/dist/api.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/** Client-safe contracts. IDs and metadata cross only the authenticated owner API, never public telemetry. */
|
|
2
2
|
import { Schema } from "effect";
|
|
3
3
|
import { HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware } from "effect/http-api";
|
|
4
|
+
import { PlanState } from "./plan.js";
|
|
4
5
|
import { StackState } from "./schema.js";
|
|
6
|
+
export { PlanRow, PlanSource, PlanState, PublishedPlan } from "./plan.js";
|
|
5
7
|
/** Random, process-scoped identity; contains no encoded provider locator. Not persisted by the server. */
|
|
6
8
|
export const StackId = Schema.String.check(Schema.isUUID());
|
|
7
9
|
export const SourceFailureReason = Schema.Literals([
|
|
@@ -55,6 +57,11 @@ const stacks = HttpApiGroup.make("stacks")
|
|
|
55
57
|
params: Schema.Struct({ id: StackId }),
|
|
56
58
|
success: StackDetail,
|
|
57
59
|
error: [StackNotFound, CatalogReadError]
|
|
60
|
+
}))
|
|
61
|
+
.add(HttpApiEndpoint.get("plan", "/stacks/:id/plan", {
|
|
62
|
+
params: Schema.Struct({ id: StackId }),
|
|
63
|
+
success: PlanState,
|
|
64
|
+
error: [StackNotFound, CatalogReadError]
|
|
58
65
|
}))
|
|
59
66
|
.prefix("/api");
|
|
60
67
|
export class AlchemyConsoleApi extends HttpApi.make("AlchemyConsoleApi").add(stacks).middleware(OwnerAuth) {
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,8GAA8G;AAC9G,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAC3F,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,0GAA0G;AAC1G,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;AAG3D,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjD,IAAI;IACJ,eAAe;IACf,kBAAkB;IAClB,qBAAqB;IACrB,OAAO;IACP,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,QAAQ;IACR,WAAW;IACX,UAAU;IACV,kBAAkB;IAClB,gBAAgB;CACjB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,EAAE,mBAAmB;CAC5B,CAAC,CAAA;AAGF,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC;IACxC,EAAE,EAAE,OAAO;IACX,GAAG,EAAE,MAAM,CAAC,cAAc;IAC1B,KAAK,EAAE,MAAM,CAAC,cAAc;IAC5B,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;CACjF,CAAC,CAAA;AAGF,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;AAEpH,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAA;AAG5E,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,EAAoB,CAAC,kBAAkB,EAAE;IAC/F,MAAM,EAAE,mBAAmB;CAC5B,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;CAAG;AAE7B,MAAM,OAAO,aAAc,SAAQ,MAAM,CAAC,WAAW,EAAiB,CAAC,eAAe,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;CAAG;AAEtH,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,WAAW,EAAgB,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;CAAG;AAEnH,MAAM,OAAO,SAAU,SAAQ,MAAM,CAAC,WAAW,EAAa,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;CAAG;AAE1G,6EAA6E;AAC7E,MAAM,OAAO,SAAU,SAAQ,iBAAiB,CAAC,OAAO,EAAa,CAAC,kCAAkC,EAAE;IACxG,KAAK,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;CACjC,CAAC;CAAG;AAEL,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;KACvC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC;KAC5F,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE;IAC7C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;IACtC,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,CAAC,aAAa,EAAE,gBAAgB,CAAC;CACzC,CAAC,CAAC;KACF,MAAM,CAAC,MAAM,CAAC,CAAA;AAEjB,MAAM,OAAO,iBAAkB,SAAQ,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC;CAAG"}
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|