@knpkv/alchemy-console 0.4.2 → 0.5.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.
Files changed (60) hide show
  1. package/README.md +67 -15
  2. package/dist/api.d.ts +87 -16
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +7 -0
  5. package/dist/api.js.map +1 -1
  6. package/dist/client/assets/{index-CHwWf6VU.css → index-D5bP19PT.css} +1 -1
  7. package/dist/client/assets/index-D9T2ytki.js +58 -0
  8. package/dist/client/index.html +2 -2
  9. package/dist/main.js +2 -1
  10. package/dist/main.js.map +1 -1
  11. package/dist/plan.d.ts +109 -0
  12. package/dist/plan.d.ts.map +1 -0
  13. package/dist/plan.js +40 -0
  14. package/dist/plan.js.map +1 -0
  15. package/dist/presentation/PlanView.d.ts +10 -0
  16. package/dist/presentation/PlanView.d.ts.map +1 -0
  17. package/dist/presentation/PlanView.js +70 -0
  18. package/dist/presentation/PlanView.js.map +1 -0
  19. package/dist/presentation/StackDetailView.d.ts +4 -1
  20. package/dist/presentation/StackDetailView.d.ts.map +1 -1
  21. package/dist/presentation/StackDetailView.js +9 -3
  22. package/dist/presentation/StackDetailView.js.map +1 -1
  23. package/dist/presentation/detail-model.d.ts +1 -1
  24. package/dist/presentation/detail-model.d.ts.map +1 -1
  25. package/dist/server/Catalog.d.ts +1 -0
  26. package/dist/server/Catalog.d.ts.map +1 -1
  27. package/dist/server/Catalog.js +7 -1
  28. package/dist/server/Catalog.js.map +1 -1
  29. package/dist/server/HttpApplication.d.ts +2 -1
  30. package/dist/server/HttpApplication.d.ts.map +1 -1
  31. package/dist/server/HttpApplication.js +3 -1
  32. package/dist/server/HttpApplication.js.map +1 -1
  33. package/dist/server/Launch.d.ts +1 -1
  34. package/dist/server/Launch.d.ts.map +1 -1
  35. package/dist/server/PlanReader.d.ts +19 -0
  36. package/dist/server/PlanReader.d.ts.map +1 -0
  37. package/dist/server/PlanReader.js +201 -0
  38. package/dist/server/PlanReader.js.map +1 -0
  39. package/dist/server/Server.d.ts +1 -1
  40. package/dist/server/Server.d.ts.map +1 -1
  41. package/dist/server/plan/archive.d.ts +10 -0
  42. package/dist/server/plan/archive.d.ts.map +1 -0
  43. package/dist/server/plan/archive.js +62 -0
  44. package/dist/server/plan/archive.js.map +1 -0
  45. package/dist/server/plan/github.d.ts +105 -0
  46. package/dist/server/plan/github.d.ts.map +1 -0
  47. package/dist/server/plan/github.js +155 -0
  48. package/dist/server/plan/github.js.map +1 -0
  49. package/dist/server/plan/receipt.d.ts +152 -0
  50. package/dist/server/plan/receipt.d.ts.map +1 -0
  51. package/dist/server/plan/receipt.js +111 -0
  52. package/dist/server/plan/receipt.js.map +1 -0
  53. package/dist/views/index.js +547 -264
  54. package/dist/views/style.css +1 -1
  55. package/dist/views.d.ts +3 -0
  56. package/dist/views.d.ts.map +1 -1
  57. package/dist/views.js +1 -0
  58. package/dist/views.js.map +1 -1
  59. package/package.json +3 -3
  60. 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. No raw JSON click target, Plan tab or Preview
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 | 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 |
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`. Both endpoints require the process's owner
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 | Result |
53
- | --------------------- | ------------------------------------------------------ |
54
- | `GET /api/stacks` | Stack summaries and explicit local/S3 discovery issues |
55
- | `GET /api/stacks/:id` | Current normalized resource state for a listed stack |
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,66 @@ 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. It verifies its
99
+ publication workflow on main, successful publisher and producer runs, PR/head/base
100
+ identity, publisher job identity, ZIP SHA-256, exact receipt fields, pinned
101
+ resource identities and the native semantic digest. Both archive and expanded
102
+ JSON must be below 1 MB. API metadata has a separate 2 MiB per-response cap to
103
+ accommodate full 100-row pages before schema projection. Metadata pagination stops
104
+ at ten pages and the whole read has a 30-second timeout. ZIP inspection and decompression stay in memory. No
105
+ payload is logged or extracted to disk.
106
+
107
+ A publication becomes stale after 24 hours or when its base differs from the
108
+ latest main commit seen by CI. A newer failed stack run can retain the verified
109
+ last publication with a stale notice. The latest attempt must have run the selected
110
+ stack’s `Native read-only plan` step. 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
+
117
+ The normalized authenticated client-visible projection contains PR number, short
118
+ head/base SHAs, publication time, safe GitHub run link, short semantic digest,
119
+ resource identity/type/action and bounded property names. These fields may cross
120
+ owner HTTP, but must not enter public or unauthenticated routes, browser storage
121
+ or telemetry. The token, signed artifact URLs, artifact/job IDs, full receipt
122
+ hashes, raw ZIP and semantic hash inputs remain server-private. Property values,
123
+ provider credentials and backend locators never enter this projection.
124
+
125
+ CI publication authenticates the source of the data, not the behavior of PR code.
126
+ The console does not certify CI's no-write or secret-access policy. No real CI
127
+ artifact is used by this feature's tests; all reader and browser states use
128
+ synthetic fixtures.
129
+
81
130
  ## Browser views
82
131
 
83
- Import `StackListView`, `StackDetailView` and `ResourceDetailView` from `@knpkv/alchemy-console/views` and its stylesheet from
132
+ Import `StackListView`, `StackDetailView`, `PlanView` and `ResourceDetailView` from `@knpkv/alchemy-console/views` and its stylesheet from
84
133
  `@knpkv/alchemy-console/views/style.css`. Mount them inside a Rly style/theme boundary.
85
134
  Views consumers supply the optional React, React DOM and Rly peers; the standalone
86
135
  browser shell already bundles them.
87
136
  The application supplies normalized presentation data, a product label, host
88
137
  sign-in instruction, read actions and real UI destinations. `StackListView` accepts
89
138
  optional `stackHref`; without a destination, stages and counts remain text.
90
- `StackDetailView` has controlled Resources/Outputs/State tabs and `resourceHref`.
139
+ `StackDetailView` has controlled Resources/Outputs/State/Plan tabs and `resourceHref`. Supply
140
+ `planState` and `onReadPlanAgain` for CI reading; without `planState`, Plan shows
141
+ Not connected. `PlanView` accepts the same controlled state and a read-only
142
+ `onReadAgain` callback.
91
143
  `ResourceDetailView` accepts `stackHref` and `resourceHref`. Views fetch nothing,
92
144
  read no configuration and persist no data. The standalone detail wrapper adds
93
145
  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<"list", "GET", "/api/stacks", never, never, never, never, Schema.toCodecJson<Schema.Struct<{
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;AAG3F,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWL,qBAAa,iBAAkB,SAAQ,sBAAmE;CAAG"}
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":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}