@lunora/config 1.0.0-alpha.5 → 1.0.0-alpha.50

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 (24) hide show
  1. package/__assets__/package-og.svg +1 -1
  2. package/dist/index.d.mts +346 -6
  3. package/dist/index.d.ts +346 -6
  4. package/dist/index.mjs +13 -9
  5. package/dist/packem_shared/{ACCENT-DN2byyj1.mjs → ACCENT-DW1XJn8i.mjs} +1 -1
  6. package/dist/packem_shared/AGENT_MODE_ENV-DM1Siczo.mjs +17 -0
  7. package/dist/packem_shared/DEV_DAEMON_ENV-FIEtW7Fz.mjs +163 -0
  8. package/dist/packem_shared/{LunoraReporter-DDGFirVv.mjs → LunoraReporter-Ci-bDCK9.mjs} +1 -1
  9. package/dist/packem_shared/{PACKAGE_SECRETS_REGISTRY-CySy5vR_.mjs → PACKAGE_SECRETS_REGISTRY-B8t_SdoZ.mjs} +9 -1
  10. package/dist/packem_shared/{POLICY_SCAFFOLD_ENDPOINT-CiC2IGKx.mjs → POLICY_SCAFFOLD_ENDPOINT-8bNMHGiu.mjs} +2 -1
  11. package/dist/packem_shared/{REQUIRED_COMPATIBILITY_DATE-ycqievRl.mjs → REQUIRED_COMPATIBILITY_DATE-2YYyWJUq.mjs} +86 -1
  12. package/dist/packem_shared/assetContentType-ByZjeV3D.mjs +72 -0
  13. package/dist/packem_shared/{buildPackageSecretsBlock-S74dgmwy.mjs → buildPackageSecretsBlock-B8iSX1Zo.mjs} +114 -20
  14. package/dist/packem_shared/collectWranglerSecretVariables-CoSGg_7B.mjs +56 -0
  15. package/dist/packem_shared/{detectFramework-Br-BcPBq.mjs → detectFramework-U08038Yp.mjs} +3 -3
  16. package/dist/packem_shared/{discoverSchemaInfo-DWtypqpP.mjs → discoverSchemaInfo-BB-CKlTK.mjs} +1 -1
  17. package/dist/packem_shared/{inferLunoraBindings-XNJH4pup.mjs → inferLunoraBindings-ByMwG-gH.mjs} +62 -12
  18. package/dist/packem_shared/{reconcileWranglerBindings-DTHmqTbL.mjs → reconcileWranglerBindings-Cruwwx1M.mjs} +60 -3
  19. package/dist/packem_shared/streamContainerLogs-BZ4cOZwH.mjs +157 -0
  20. package/dist/studio-host/index.d.mts +33 -1
  21. package/dist/studio-host/index.d.ts +33 -1
  22. package/dist/studio-host/index.mjs +2 -2
  23. package/package.json +9 -6
  24. package/dist/packem_shared/loadStudioAssets-Csk5RS4E.mjs +0 -28
package/dist/index.d.mts CHANGED
@@ -1,7 +1,25 @@
1
- import { ContainerIR, WorkflowIR } from '@lunora/codegen';
1
+ import { ContainerIR, WorkflowIR, QueueIR, WranglerVariableIR } from '@lunora/codegen';
2
2
  export type { ContainerIR, WorkflowIR } from '@lunora/codegen';
3
+ import { Writable } from 'node:stream';
3
4
  import 'ts-morph';
4
5
  export { type A as AdditivePolicyEdit, type D as DestructivePolicyEdit, type P as PolicyEdit, type a as PolicyScaffoldFailureReason, type b as ScaffoldFileResult, type S as ScaffoldPolicyEdit, type c as WireResult, type W as WireRlsEdit, d as classifyPolicyEdit, s as scaffoldPolicyFile, w as wireRlsIntoProcedure } from "./packem_shared/policy-scaffold.d-DCmwn7zQ.mjs";
6
+ /** Minimal env shape — `process.env` structurally, injectable for tests. */
7
+ type EnvLike = Readonly<Record<string, string | undefined>>;
8
+ /** One detected agent: which tool, and which env var gave it away. */
9
+ interface AgentDetection {
10
+ /** Human-readable agent name, for the "agent detected" log line. */
11
+ name: string;
12
+ /** The environment variable that matched. */
13
+ variable: string;
14
+ }
15
+ /** Env var that forces agent mode on (`1`/`true`) or off (`0`/`false`), overriding detection. */
16
+ declare const AGENT_MODE_ENV = "LUNORA_AGENT_MODE";
17
+ /**
18
+ * Detect the AI agent driving this process, or `undefined` when none is.
19
+ * `LUNORA_AGENT_MODE` wins over `@visulima/find-ai-runner`'s marker table in
20
+ * both directions. Pure — pass a custom `env` in tests.
21
+ */
22
+ declare const detectAiAgent: (env?: EnvLike) => AgentDetection | undefined;
5
23
  /**
6
24
  * Project-relative directory the Lunora agent skills ("rules") install into.
7
25
  * This is the portable [Agent Skills](https://tanstack.com/intent/latest/docs/registry)
@@ -65,6 +83,77 @@ interface DiscoverContainerInfoResult {
65
83
  * (inference).
66
84
  */
67
85
  declare const discoverContainerInfo: (projectRoot: string, schemaDirectory: string) => DiscoverContainerInfoResult;
86
+ /** Severity a container output line is surfaced at: `stderr` → `error`, `stdout` → `info`. */
87
+ type ContainerLogLevel = "error" | "info";
88
+ /** One declared container to follow, identified by the names codegen lifts from `defineContainer`. */
89
+ interface ContainerLogSource {
90
+ /** Generated Durable Object class name, e.g. `TranscoderContainer`. Wrangler's dev image is `cloudflare-dev/&lt;lowercased>`. */
91
+ className: string;
92
+ /** The `lunora/containers.ts` export name, e.g. `transcoder` — used as the display tag. */
93
+ exportName: string;
94
+ }
95
+ /** A single line of container output handed back to the caller. */
96
+ interface ContainerLogLine {
97
+ /** `"error"` for the container's stderr, `"info"` for its stdout. */
98
+ level: ContainerLogLevel;
99
+ /** The container's export name (`transcoder`), for tagging the line. */
100
+ name: string;
101
+ /** One output line, with the trailing newline (and any `\r`) stripped. */
102
+ text: string;
103
+ }
104
+ interface ContainerLogStreamOptions {
105
+ /** The declared containers to follow. An empty list yields an inert handle. */
106
+ containers: ReadonlyArray<ContainerLogSource>;
107
+ /** Injected Docker client — defaults to a real lazily-imported `dockerode` instance. Tests pass a stub. */
108
+ docker?: DockerLike;
109
+ /** Called once per container output line. */
110
+ onLine: (line: ContainerLogLine) => void;
111
+ /** Called once when the Docker engine can't be reached (re-armed after it recovers). Defaults to silent. */
112
+ onUnavailable?: (message: string) => void;
113
+ /** Poll interval override, in ms. */
114
+ pollIntervalMs?: number;
115
+ }
116
+ /** Handle controlling a running log stream. */
117
+ interface ContainerLogStreamHandle {
118
+ /** Stop polling and tear down every attached log stream. Idempotent. */
119
+ close: () => void;
120
+ }
121
+ /** The minimal structural slice of a `dockerode` log stream this module consumes. */
122
+ interface DockerLogStream {
123
+ destroy: () => void;
124
+ on: (event: "data" | "end" | "error", listener: (chunk?: Buffer) => void) => void;
125
+ }
126
+ /** The minimal structural slice of a `dockerode` instance this module consumes. */
127
+ interface DockerLike {
128
+ getContainer: (id: string) => {
129
+ logs: (options: {
130
+ follow: true;
131
+ stderr: true;
132
+ stdout: true;
133
+ tail: "all";
134
+ timestamps: false;
135
+ }) => Promise<DockerLogStream>;
136
+ };
137
+ listContainers: (options: {
138
+ filters: {
139
+ status: ["running"];
140
+ };
141
+ }) => Promise<{
142
+ Id: string;
143
+ Image: string;
144
+ }[]>;
145
+ modem: {
146
+ demuxStream: (stream: DockerLogStream, stdout: Writable, stderr: Writable) => void;
147
+ };
148
+ }
149
+ /**
150
+ * Follow the local Docker logs of every declared container, emitting each output
151
+ * line through `onLine` tagged with its export name. Polls for containers (they
152
+ * start lazily on first request and may be replaced on restart), attaches once
153
+ * per container id, and drops streams whose container has gone. Returns
154
+ * immediately with a `close()` handle; all work happens asynchronously.
155
+ */
156
+ declare const streamContainerLogs: (options: ContainerLogStreamOptions) => ContainerLogStreamHandle;
68
157
  /**
69
158
  * The meta-frameworks Lunora can compose with, plus `"none"` for a standalone
70
159
  * SPA / SSR-less project (the current default). Mirrors PLAN4 §2.4.
@@ -85,6 +174,13 @@ interface FrameworkDetection {
85
174
  framework: DetectedFramework;
86
175
  }
87
176
  /**
177
+ * Read and parse the project `package.json`, returning its merged
178
+ * `dependencies` + `devDependencies` name set (empty on any failure). Public
179
+ * so sibling consumers (e.g. the CLI's Vite-project detection) share one
180
+ * best-effort reader instead of re-parsing `package.json` themselves.
181
+ */
182
+ declare const readProjectDependencyNames: (root: string) => ReadonlySet<string>;
183
+ /**
88
184
  * Detect which meta-framework a project uses by inspecting its `package.json`
89
185
  * dependencies, and classify it under void's class-A/B/C model (PLAN4 §3).
90
186
  *
@@ -93,6 +189,112 @@ interface FrameworkDetection {
93
189
  * SPA flow is preserved.
94
190
  */
95
191
  declare const detectFramework: (root: string) => FrameworkDetection;
192
+ /** Directory holding per-checkout Lunora state (gitignored by convention). */
193
+ declare const DEV_STATE_DIR = ".lunora";
194
+ /** The dev-server state filename, relative to the project root. */
195
+ declare const DEV_STATE_FILE: string;
196
+ /** Log file a backgrounded dev server's output is captured to, relative to the project root. */
197
+ declare const DEV_LOG_FILE: string;
198
+ /**
199
+ * Marker env `lunora dev --background` sets on the detached server process
200
+ * (the daemon `lunora dev` or `vite dev`), so it records itself as
201
+ * `background: true` — and, for the CLI daemon, never re-detects an agent and
202
+ * recurses into background mode again.
203
+ */
204
+ declare const DEV_DAEMON_ENV = "LUNORA_DEV_DAEMON";
205
+ /** Env carrying the capture-log path into the detached server, recorded in the state file. */
206
+ declare const DEV_LOG_FILE_ENV = "LUNORA_DEV_LOG_FILE";
207
+ /**
208
+ * Env carrying the PID of a parent that holds a *provisional* state record it
209
+ * expects the child dev server to supersede. The CLI claims `.lunora/dev.json`
210
+ * with its own PID before spawning the real server (closing the duplicate-start
211
+ * race for the vite flavor and the wrangler daemon), then hands its PID down
212
+ * via this variable; the child's claim (see {@link claimDevServerState}'s
213
+ * `supersedePid`) may replace exactly that record with the authoritative
214
+ * URL + PID.
215
+ */
216
+ declare const DEV_HANDOFF_ENV = "LUNORA_DEV_HANDOFF_PID";
217
+ /** How the recorded dev server runs. */
218
+ type DevServerMode = "cli" | "vite";
219
+ /** The state record persisted to `.lunora/dev.json`. */
220
+ interface DevServerState {
221
+ /** Whether the server was detached into the background (`lunora dev --background`). */
222
+ background?: boolean;
223
+ /** Absolute path of the log file capturing the server's output, when captured. */
224
+ logFile?: string;
225
+ /** `"cli"` for the `lunora dev` wrangler orchestration, `"vite"` for a Vite dev server. */
226
+ mode: DevServerMode;
227
+ /** PID of the process to signal for shutdown (the orchestrating CLI or the Vite process). */
228
+ pid: number;
229
+ /** ISO-8601 stamp written at startup, purely informational (drives `status` uptime). */
230
+ startedAt?: string;
231
+ /** The embedded studio server's URL, when it runs. */
232
+ studioUrl?: string;
233
+ /** The primary URL serving the worker/app. */
234
+ url: string;
235
+ }
236
+ /**
237
+ * True when a process with `pid` is currently alive AND signalable by this
238
+ * user. Signal `0` performs the existence check without delivering anything.
239
+ *
240
+ * `EPERM` ("alive but another user's process") deliberately counts as NOT
241
+ * alive here: every dev server this module tracks was spawned by the current
242
+ * user, so a PID we cannot signal is by definition a recycled PID — treating
243
+ * it as running would wedge the lockfile permanently and aim `dev stop`'s
244
+ * kill escalation at an innocent process.
245
+ */
246
+ declare const isProcessAlive: (pid: number) => boolean;
247
+ /**
248
+ * True when the record's PID verifiably still refers to the dev server that
249
+ * wrote the record — not merely "some process exists with that number".
250
+ * Guards against PID reuse: a server process necessarily starts BEFORE its
251
+ * record is written, so a process that started after `startedAt` (+ skew) is
252
+ * a recycled PID wearing the corpse's number. The start-time check runs only
253
+ * where the platform exposes it (Linux); elsewhere liveness alone decides.
254
+ */
255
+ declare const isRecordedProcessCurrent: (state: DevServerState) => boolean;
256
+ /**
257
+ * Read the state record from `.lunora/dev.json`, or `undefined` when there is
258
+ * no usable record. Best-effort; performs NO liveness check — use
259
+ * {@link readLiveDevServerState} for "is a dev server actually running".
260
+ */
261
+ declare const readDevServerState: (projectRoot: string) => DevServerState | undefined;
262
+ /**
263
+ * Write the state record to `.lunora/dev.json`, creating the `.lunora/`
264
+ * directory when absent. Returns the absolute path written, or `undefined`
265
+ * when the write failed (state is convenience metadata — a read-only checkout
266
+ * must never crash dev startup).
267
+ */
268
+ declare const writeDevServerState: (projectRoot: string, state: DevServerState) => string | undefined;
269
+ /**
270
+ * Merge `patch` into the existing state record, when one exists. Used by the
271
+ * CLI to stamp `background`/`logFile` onto the record the Vite plugin wrote.
272
+ * Returns the merged record, or `undefined` when there was nothing to update.
273
+ */
274
+ declare const updateDevServerState: (projectRoot: string, patch: Partial<DevServerState>) => DevServerState | undefined;
275
+ /**
276
+ * Remove `.lunora/dev.json`. Idempotent and never throws. When `expectedPid`
277
+ * is given, the file is only removed while it still records that PID — so a
278
+ * shutting-down server can't clobber the record a newer server just wrote.
279
+ */
280
+ declare const clearDevServerState: (projectRoot: string, expectedPid?: number) => void;
281
+ /**
282
+ * The state record of a dev server that is verifiably running right now, or
283
+ * `undefined`. A record whose PID is dead — or recycled onto a different
284
+ * process (see {@link isRecordedProcessCurrent}) — is stale: it is cleared on
285
+ * the spot so subsequent starts don't keep re-reading a corpse.
286
+ */
287
+ declare const readLiveDevServerState: (projectRoot: string) => DevServerState | undefined;
288
+ /** Result of {@link claimDevServerState}: claimed, or lost to the live server already recorded. */
289
+ interface ClaimDevServerStateResult {
290
+ /** The live record that won the race, when `ok` is `false`. */
291
+ existing?: DevServerState;
292
+ /** Whether this process now owns the record. */
293
+ ok: boolean;
294
+ }
295
+ declare const claimDevServerState: (projectRoot: string, state: DevServerState, options?: {
296
+ supersedePid?: number;
297
+ }) => ClaimDevServerStateResult;
96
298
  /**
97
299
  * The `.dev.vars` line grammar — one owner, shared by every reader/writer of the
98
300
  * file so the format can't drift between packages. `@lunora/cli`'s `env`
@@ -156,34 +358,52 @@ interface InferredContainer extends ContainerIR {
156
358
  interface InferredWorkflow extends WorkflowIR {
157
359
  exported: boolean;
158
360
  }
361
+ /**
362
+ * A queue declared in `lunora/queues.ts`. Unlike workflows, a queue needs no
363
+ * worker-entry class export (its `queue()` handler rides `createWorker`), so
364
+ * there is no `exported` flag — every declared queue is reconcilable into the
365
+ * wrangler `queues.producers[]` / `queues.consumers[]`.
366
+ */
367
+ type InferredQueue = QueueIR;
159
368
  interface InferredBindings {
160
369
  /** Containers declared in `lunora/containers.ts` (exported or not — see {@link InferredContainer.exported}). */
161
370
  containers: InferredContainer[];
162
371
  /** Durable Objects the worker entry exports → safe to bind. */
163
372
  durableObjects: DurableObjectSpec[];
373
+ /**
374
+ * The wrangler `flagship[].binding` name implied by `lunora/flags.ts` when it
375
+ * uses the Flagship provider in binding mode — `undefined` for HTTP-mode
376
+ * Flagship, a custom OpenFeature provider, or no flags. The binding needs an
377
+ * un-mintable `app_id`, so it is reconciled as a hint, not auto-written.
378
+ */
379
+ flagshipBinding?: string;
164
380
  /** Schema declares a `.global()` table → needs the `DB` D1 binding. */
165
381
  needsD1: boolean;
382
+ /** Queues declared in `lunora/queues.ts` → reconciled into `queues.producers[]` / `queues.consumers[]`. */
383
+ queues: InferredQueue[];
166
384
  /** Human-readable provenance for each inferred binding / hint, for logging. */
167
385
  signals: string[];
168
386
  /** `@lunora/ai` is imported or `env.AI` is used → needs the `ai` Workers AI binding. */
169
387
  usesAi: boolean;
170
- /** `@lunora/analytics` is imported → self-describing `analytics_engine_datasets` binding (auto-writeable). */
388
+ /** `@lunora/bindings/analytics` is imported → self-describing `analytics_engine_datasets` binding (auto-writeable). */
171
389
  usesAnalytics: boolean;
172
390
  /** `@lunora/auth` is imported (sessions may be D1- or `SessionDO`-backed). */
173
391
  usesAuth: boolean;
174
392
  /** `@lunora/browser` is imported → self-describing `browser` binding (auto-writeable). */
175
393
  usesBrowser: boolean;
394
+ /** `lunora/flags.ts` declares a feature-flag provider (any OpenFeature provider — Flagship or custom). */
395
+ usesFlags: boolean;
176
396
  /** `@lunora/hyperdrive` is imported (binding needs an un-mintable remote `id`; hint-only). */
177
397
  usesHyperdrive: boolean;
178
- /** `@lunora/images` is imported → self-describing `images` binding (auto-writeable). */
398
+ /** `@lunora/bindings/images` is imported → self-describing `images` binding (auto-writeable). */
179
399
  usesImages: boolean;
180
- /** `@lunora/kv` is imported (namespace binding name + id are user-defined; hint-only). */
400
+ /** `@lunora/bindings/kv` is imported (namespace binding name + id are user-defined; hint-only). */
181
401
  usesKv: boolean;
182
402
  /** `@lunora/mail` is imported (Resend API key must be set in `.dev.vars`; no binding). */
183
403
  usesMail: boolean;
184
404
  /** `@lunora/payment` is imported (provider secrets must be set in `.dev.vars`; no binding). */
185
405
  usesPayment: boolean;
186
- /** `@lunora/pipelines` is imported (binding needs an un-mintable remote pipeline name; hint-only). */
406
+ /** `ctx.pipelines` is used (binding needs an un-mintable remote pipeline name; hint-only). */
187
407
  usesPipelines: boolean;
188
408
  /** `@lunora/scheduler` is imported. */
189
409
  usesScheduler: boolean;
@@ -338,6 +558,15 @@ interface SecretEntry {
338
558
  */
339
559
  placeholderValue: string;
340
560
  }
561
+ /**
562
+ * Secrets every Lunora project needs regardless of which capability packages are
563
+ * installed — scaffolded into `.dev.vars` always. `LUNORA_ADMIN_TOKEN` is the
564
+ * bearer the local Studio uses to call the worker's admin endpoints (the data
565
+ * browser, schema edits) in dev; the worker reads the SAME `.dev.vars` value via
566
+ * its admin gate, so both agree and the Studio authenticates without a prompt.
567
+ * Without it, every `/_lunora/admin/*` call is `ADMIN_FORBIDDEN` (403).
568
+ */
569
+
341
570
  /**
342
571
  * The canonical registry of per-package secret requirements.
343
572
  *
@@ -659,6 +888,8 @@ interface RemoteEnableInputs {
659
888
  * is still overridable per-run by `--remote` or `LUNORA_REMOTE=1`.
660
889
  */
661
890
  declare const resolveRemoteEnabled: (inputs: RemoteEnableInputs) => boolean;
891
+ /** Core (always-scaffolded) secrets followed by the package-specific ones for the detected capabilities. */
892
+ declare const requiredSecrets: (packageNames: ReadonlyArray<string>) => SecretEntry[];
662
893
  /**
663
894
  * Whether an (already-unquoted) value looks like a fill-me-in placeholder —
664
895
  * empty, angle-bracketed, or containing a known marker — rather than a real
@@ -667,6 +898,15 @@ declare const resolveRemoteEnabled: (inputs: RemoteEnableInputs) => boolean;
667
898
  */
668
899
  declare const isPlaceholderValue: (value: string) => boolean;
669
900
  /**
901
+ * True for a secret-looking key whose value Lunora can mint locally (a random
902
+ * 32-byte hex, like `openssl rand -hex 32`) — e.g. `AUTH_SECRET`,
903
+ * `LUNORA_ADMIN_TOKEN`, `STORAGE_SIGNING_SECRET`. False for provider-issued keys
904
+ * ({@link PROVIDER_SECRET_KEYS}) and any non-secret key.
905
+ */
906
+ declare const isMintableSecretKey: (key: string) => boolean;
907
+ /** Mint a fresh strong secret value — 64 hex chars (32 bytes), like `openssl rand -hex 32`. */
908
+ declare const generateSecretValue: (randomHex?: (bytes: number) => string) => string;
909
+ /**
670
910
  * The outcome of planning a scaffold — a discriminated union so the orchestrator
671
911
  * never has to re-derive whether `content` is present.
672
912
  *
@@ -768,6 +1008,58 @@ declare const buildPackageSecretsBlock: (packageNames: ReadonlyArray<string>, ex
768
1008
  * **Safety invariant:** only placeholder values are written — no real secrets.
769
1009
  */
770
1010
  declare const ensureDevVariablesExample: (cwd: string, packageNames: ReadonlyArray<string>) => string[];
1011
+ interface DevSecretsFillPlan {
1012
+ /** {@link CORE_SECRETS} keys appended because they were absent (each generated). */
1013
+ addedKeys: string[];
1014
+ /** The full new file content to write. */
1015
+ content: string;
1016
+ /** Existing empty/placeholder secret-keyed entries filled with fresh values. */
1017
+ filledKeys: string[];
1018
+ }
1019
+ /**
1020
+ * Plan the in-place generation of dev secrets for a `.dev.vars`. First, every
1021
+ * line whose KEY looks like a secret (`*_SECRET`, `*_TOKEN`, `*_KEY`,
1022
+ * `*_PASSWORD`) and whose value is empty or a placeholder gets a freshly
1023
+ * generated value — so a `lunora add`-scaffolded `.dev.vars` (which writes each
1024
+ * secret blank) becomes usable on `lunora dev` / `vite dev` without the user
1025
+ * running `openssl` by hand. Second, any {@link CORE_SECRETS} key absent from
1026
+ * the file is appended (generated) — notably `LUNORA_ADMIN_TOKEN`, which the
1027
+ * local Studio needs to call the worker's admin gate in dev (without it the
1028
+ * Studio shows its login gate).
1029
+ *
1030
+ * Pure (given `randomHex`): real (non-placeholder) values are never touched, and
1031
+ * comments + non-secret entries are preserved verbatim.
1032
+ */
1033
+ declare const planDevSecretsFill: (input: {
1034
+ existingContent: string;
1035
+ randomHex?: (bytes: number) => string;
1036
+ }) => DevSecretsFillPlan;
1037
+ interface FillDevSecretsResult {
1038
+ /** Core secret keys appended (generated) because they were missing. */
1039
+ addedKeys: string[];
1040
+ /** Existing empty/placeholder secrets filled with generated values. */
1041
+ filledKeys: string[];
1042
+ /** `created` = no `.dev.vars` existed; `filled` = topped up an existing one; `unchanged` = nothing to do. */
1043
+ status: "created" | "filled" | "unchanged";
1044
+ }
1045
+ /**
1046
+ * Generate any missing/empty dev secrets in the project's `.dev.vars`, in place.
1047
+ *
1048
+ * Complements {@link ensureDevVariables} (which scaffolds `.dev.vars` from
1049
+ * `.dev.vars.example`). A `lunora add`-scaffolded project writes secrets blank
1050
+ * straight into `.dev.vars` (no example) and never includes `LUNORA_ADMIN_TOKEN`
1051
+ * — so the worker boots with empty secrets and the Studio shows its login gate.
1052
+ * This fills those gaps at dev startup, so both `lunora dev` and the
1053
+ * `@lunora/vite` dev server give a working project with zero manual `openssl`.
1054
+ *
1055
+ * Never overwrites a real (non-placeholder) value. The write is atomic + owner-
1056
+ * only (temp + rename, `mode: 0o600`), matching the other `.dev.vars` writers.
1057
+ */
1058
+ declare const fillDevSecrets: (deps: {
1059
+ cwd: string;
1060
+ info?: (message: string) => void;
1061
+ randomHex?: (bytes: number) => string;
1062
+ }) => FillDevSecretsResult;
771
1063
  /** Add a new table to `defineSchema({ ... })`. */
772
1064
  interface AddTableEdit {
773
1065
  readonly kind: "addTable";
@@ -939,6 +1231,8 @@ declare const LUNA_ART: string;
939
1231
  declare const padBadge: (text: string) => string;
940
1232
  /** Leading spaces that right-align a badge's box within the gutter. */
941
1233
  declare const badgeLead: (text: string) => string;
1234
+ /** Total columns a rendered badge column occupies (lead + box), constant across badges. */
1235
+ declare const BADGE_COLUMN_WIDTH: number;
942
1236
  /** Columns a rendered badge occupies — the gutter-aligned column width. */
943
1237
  declare const badgeWidth: (_spec: BadgeSpec) => number;
944
1238
  /** Paint a badge as an ANSI string (the non-tui path): right-aligning spaces + the colored box. */
@@ -962,6 +1256,23 @@ interface ReadWranglerResult<T> {
962
1256
  * wrangler does.
963
1257
  */
964
1258
  declare const readWranglerJsonc: <T = unknown>(wranglerPath: string) => ReadWranglerResult<T>;
1259
+ /**
1260
+ * Pure scan of a `vars` map for plaintext secrets — the FS-free core, exported for
1261
+ * unit tests. A variable is flagged when, for a **string** value that is neither a
1262
+ * placeholder nor a public/publishable key, EITHER the value matches a known
1263
+ * secret shape (`secretKindOf`) OR the key name strongly implies a secret and the
1264
+ * value is long enough to plausibly be one. `kind` is the matched shape, or
1265
+ * `secret_named_var` for the key-name path.
1266
+ */
1267
+ declare const scanWranglerVariablesForSecrets: (variables: Record<string, unknown> | undefined, file: string) => WranglerVariableIR[];
1268
+ /**
1269
+ * Read the project's `wrangler.jsonc` and return its plaintext-secret `vars` as IR
1270
+ * for the `plaintext_secret_in_wrangler_vars` lint. Returns `[]` when there is no
1271
+ * wrangler config, it doesn't parse, or nothing looks like a secret. Scans the
1272
+ * top-level `vars` block (mirroring the existing `validateCorsVariables` scope);
1273
+ * per-environment `env.&lt;name>.vars` overrides are out of scope for now.
1274
+ */
1275
+ declare const collectWranglerSecretVariables: (projectRoot: string) => WranglerVariableIR[];
965
1276
  declare const REQUIRED_COMPATIBILITY_DATE: string;
966
1277
  declare const REQUIRED_FLAG: string;
967
1278
  interface WranglerDurableObjectBinding {
@@ -1000,6 +1311,22 @@ interface WranglerWorkflowEntry {
1000
1311
  class_name?: string;
1001
1312
  name?: string;
1002
1313
  }
1314
+ /** A wrangler `queues.producers[]` entry — a `Queue` binding sending to `queue`. */
1315
+ interface WranglerQueueProducer {
1316
+ binding?: string;
1317
+ delivery_delay?: number;
1318
+ queue?: string;
1319
+ }
1320
+ /** A wrangler `queues.consumers[]` entry — push (worker) or `type: "http_pull"`. */
1321
+ interface WranglerQueueConsumer {
1322
+ dead_letter_queue?: string;
1323
+ max_batch_size?: number;
1324
+ max_batch_timeout?: number;
1325
+ max_retries?: number;
1326
+ queue?: string;
1327
+ retry_delay?: number;
1328
+ type?: string;
1329
+ }
1003
1330
  interface WranglerConfig {
1004
1331
  analytics_engine_datasets?: ReadonlyArray<{
1005
1332
  binding?: string;
@@ -1028,6 +1355,10 @@ interface WranglerConfig {
1028
1355
  durable_objects?: {
1029
1356
  bindings?: ReadonlyArray<WranglerDurableObjectBinding>;
1030
1357
  };
1358
+ flagship?: ReadonlyArray<{
1359
+ app_id?: string;
1360
+ binding?: string;
1361
+ } | null | undefined>;
1031
1362
  hyperdrive?: ReadonlyArray<{
1032
1363
  binding?: string;
1033
1364
  id?: string;
@@ -1064,9 +1395,18 @@ interface WranglerConfig {
1064
1395
  placement?: {
1065
1396
  mode?: string;
1066
1397
  };
1398
+ queues?: {
1399
+ consumers?: ReadonlyArray<WranglerQueueConsumer | null | undefined>;
1400
+ producers?: ReadonlyArray<WranglerQueueProducer | null | undefined>;
1401
+ };
1067
1402
  r2_buckets?: ReadonlyArray<{
1068
1403
  binding?: string;
1069
1404
  }>;
1405
+ secrets_store_secrets?: ReadonlyArray<{
1406
+ binding?: string;
1407
+ secret_name?: string;
1408
+ store_id?: string;
1409
+ } | null | undefined>;
1070
1410
  send_email?: ReadonlyArray<{
1071
1411
  allowed_destination_addresses?: ReadonlyArray<string>;
1072
1412
  destination_address?: string;
@@ -1126,4 +1466,4 @@ interface WranglerProjectValidationResult {
1126
1466
  * `{ problems, wranglerPath }` shape plus the structured `report`.
1127
1467
  */
1128
1468
  declare const validateWranglerProject: (options: WranglerProjectValidationOptions) => WranglerProjectValidationResult;
1129
- export { ACCENT, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, type BadgeName, type BadgeSpec, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FrameworkClass, type FrameworkDetection, type InferOptions, type InferredBindings, type InferredContainer, type InferredWorkflow, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MaterializeOptions, type MaterializeResult, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, ROOT_SKILL_NAME, type ReadWranglerResult, type ReconcileBindingsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemotePreference, type RemoteWranglerShape, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaInfo, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type TailConsumer, WRANGLER_FILES, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, classifyEdit, createConfirm, detectAgentRules, detectFramework, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, findWranglerFile, formatLunoraEvent, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isPlaceholderValue, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptYesNo, readLinkedProject, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, resolveRemoteEnabled, secretsForPackages, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeLinkedProject };
1469
+ export { ACCENT, AGENT_MODE_ENV, AGENT_RULES_DIR, AGENT_RULES_HINT, AGENT_RULES_HINT_ENV, type AddIndexEdit, type AddOptionalColumnEdit, type AddTableEdit, type AdditiveEdit, type AgentDetection, type AgentRulesStatus, type ApplyEditResult, type ApplyFailureReason, type AugmentPlan, BADGES, BADGE_COLUMN_WIDTH, type BadgeName, type BadgeSpec, type ClaimDevServerStateResult, type ContainerLogLevel, type ContainerLogLine, type ContainerLogSource, type ContainerLogStreamHandle, type ContainerLogStreamOptions, DEV_DAEMON_ENV, DEV_HANDOFF_ENV, DEV_LOG_FILE, DEV_LOG_FILE_ENV, DEV_STATE_DIR, DEV_STATE_FILE, DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, type DestructiveEdit, type DetectedFramework, type DevSecretsFillPlan, type DevServerMode, type DevServerState, type DiscoverContainerInfoResult, type DiscoverSchemaInfoResult, type DiscoverWorkflowInfoResult, type DockerLike, type EnsureDevVariablesDeps, type EnsureDevVariablesResult, type EnsureDevVariablesStatus, type ExportGap, type FillDevSecretsResult, type FrameworkClass, type FrameworkDetection, type InferOptions, type InferredBindings, type InferredContainer, type InferredWorkflow, LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, LUNORA_CONFIG_FILE, LUNORA_EVENT_SOURCE, LUNORA_SKILL_NAMES, type LevelBadgeName, type LinkedProject, type LunoraFormattedLine, type LunoraLineLevel, type LunoraProjectConfig, LunoraReporter, type MaterializeOptions, type MaterializeResult, type MultiSelectOption, PACKAGE_SECRETS_REGISTRY, type ParseSchemaResult, REMOTE_ELIGIBLE_KEYS, REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, ROOT_SKILL_NAME, type ReadWranglerResult, type ReconcileBindingsResult, type RemoteBindingPlan, type RemoteEnableInputs, type RemotePreference, type RemoteWranglerShape, STEP_BADGE_NAMES, type ScaffoldPlan, type SchemaColumn, type SchemaEdit, type SchemaIndex, type SchemaInfo, type SchemaTable, type SecretEntry, type SelectOption, type StepBadgeName, type TailConsumer, WRANGLER_FILES, type WranglerConfig, type WranglerContainerEntry, type WranglerProjectValidationOptions, type WranglerProjectValidationResult, type WranglerValidationReport, type WranglerWorkflowEntry, applyAdditiveEdit, badgeLead, badgeWidth, buildPackageSecretsBlock, claimAgentRulesHint, claimDevServerState, classifyEdit, clearDevServerState, collectWranglerSecretVariables, createConfirm, detectAgentRules, detectAiAgent, detectFramework, discoverContainerInfo, discoverSchemaInfo, discoverWorkflowInfo, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, findWranglerFile, formatLunoraEvent, generateSecretValue, inferLunoraBindings, injectRemoteFlags, interpretRemote, isInteractive, isMintableSecretKey, isPlaceholderValue, isProcessAlive, isRecordedProcessCurrent, isRemoteEnvEnabled, materializeRemoteWranglerConfig, packageNamesFromBindings, padBadge, paintAnswer, paintBadge, parseDevVariableEntries, parseSchema, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, planRemoteBindings, promptMultiSelect, promptSelect, promptYesNo, readDevServerState, readLinkedProject, readLiveDevServerState, readProjectDependencyNames, readProjectRemotePreference, readWranglerJsonc, reconcileWranglerBindings, requiredSecrets, resolveRemoteEnabled, scanWranglerVariablesForSecrets, secretsForPackages, streamContainerLogs, updateDevServerState, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer, writeDevServerState, writeLinkedProject };