@warlock.js/core 5.34.0 → 5.34.2

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/llms-full.txt CHANGED
@@ -4,6 +4,47 @@
4
4
 
5
5
  > Generated artifact. Concatenates every SKILL.md and reference file under `@warlock.js/core/skills/`. Re-run `node scripts/generate-llms.mjs` after any change.
6
6
 
7
+ ## Package orientation
8
+
9
+ ---
10
+ description: "The Warlock server framework: HTTP routes, controllers, responses, resources, repositories, CLI, mail, storage, security helpers. Exports `router`, `Request`, `Response`, `RequestHandler`, `useCase`, `RepositoryManager`, `defineResource`, `defineConfig`, `storage`, `sendMail`, `hashPassword`, `command`. Use for: add a route, write a controller, return a JSON response, hide a field from the response, upload a file, send an email, hash a password, add a CLI command, generate an OpenAPI document, type an API response, wire a socket, run or configure the app. Not this package: database models/queries → @warlock.js/cascade; input schemas → @warlock.js/seal; SSR pages → @warlock.js/web."
11
+ ---
12
+
13
+ # @warlock.js/core
14
+
15
+ Core is the application runtime: it boots the app, auto-loads each module's special files, serves HTTP, and provides the helpers every feature layer uses. Features live in `src/app/<module>/` and flow one way: `routes.ts → controllers → services → repositories → models`; resources map output at the edge. Start with `warlock-conventions.md`, which every other topic assumes.
16
+
17
+ ## The 80% path
18
+
19
+ 1. Scaffold a module (`create-module.md`), then declare routes in its `routes.ts` (`register-route.md`, `warlock-routes.md`).
20
+ 2. Write a thin controller (`create-controller.md`); validate input with a schema attached to the handler (`validate-input.md`).
21
+ 3. Put logic in a service or use case (`write-use-case.md`), and data access in a repository (`use-repository.md`).
22
+ 4. Return via `response.*` (`send-response.md`) and shape output with a resource (`define-resource.md`); declare `responseSchema` for typed clients and docs (`create-controller.md`, `generate-openapi.md`).
23
+ 5. Configure and run (`configure-app.md`, `run-app.md`); check setup with `warlock-doctor.md`, read the app with `warlock-inspect.md` (or serve it to an agent with `warlock-mcp.md`), verify a change with `warlock-check.md`, and a request's runtime behaviour with `warlock-trace.md`.
24
+
25
+ When the framework is wrong or missing a capability, follow the `report-framework-issue` topic to prepare a public report and ask the user before filing.
26
+
27
+ ## Topics by area
28
+
29
+ - **Foundations:** warlock-conventions, create-module, make-endpoint, configure-app, use-app-context, resolve-path, build-url, update-packages, lower-stage3-decorators, upgrade-from-5-29
30
+ - **HTTP & routing:** register-route, warlock-routes, create-controller, use-middleware, write-middleware, validate-input, use-request-locals, build-restful, wire-socket
31
+ - **Responses & resources:** send-response, define-resource, use-model-transformers, use-localization
32
+ - **Domain layers:** write-use-case, use-repository, write-seeder
33
+ - **CLI & running the app:** run-app, write-cli-command, add-connector, health-checks, warlock-doctor, warlock-inspect, warlock-check, generate-openapi
34
+ - **Agent tooling:** warlock-mcp, warlock-trace, warlock-agents-md, warlock-board
35
+ - **Storage, files & mail:** store-file, upload-file, process-image, send-mail
36
+ - **Security & utilities:** hash-password, encrypt-data, store-secrets, retry-operation, benchmark-code, request-memo, request-tracing
37
+ - **Testing:** test-browser, test-http, test-service, test-fakes, model-factories
38
+
39
+ ## Conventions and pitfalls
40
+
41
+ - Several files are auto-loaded (`routes.ts`, `main.ts`, `events/*`, `utils/locales.ts`, `src/config/*`); never import them by hand.
42
+ - Core does NOT re-export `v`/`Infer` (import from `@warlock.js/seal`), or `Model`/`Migration` (from `@warlock.js/cascade`).
43
+ - Controllers stay thin: no business logic, transactions, or external API calls. Resources are output-only.
44
+ - No per-action `*.request.ts` files; schema files export the value and the inferred type together.
45
+ - Prefer typed model getters over scattered `.get<T>("field")` casts.
46
+
47
+
7
48
  ## add-connector `@warlock.js/core/add-connector/SKILL.md`
8
49
 
9
50
  ---
@@ -3745,6 +3786,169 @@ router.get("/webhooks/status", webhookStatusController, { rateLimit: false });
3745
3786
  - The `warlock-conventions` topic — module layout, the `guarded` convention, path aliases.
3746
3787
 
3747
3788
 
3789
+ ## report-framework-issue `@warlock.js/core/report-framework-issue/SKILL.md`
3790
+
3791
+ ---
3792
+ name: report-framework-issue
3793
+ description: "Report a confirmed Warlock.js framework bug or missing capability. Read when behavior contradicts the installed docs, a crash appears to originate in @warlock.js packages, or no documented API meets a requirement; covers minimal reproduction, duplicate searches, sanitized warlock issue output and user approval before filing."
3794
+ ---
3795
+
3796
+ # Report a Warlock.js framework issue
3797
+
3798
+ Use this topic when behavior contradicts the installed version's docs or skills,
3799
+ a crash originates inside `@warlock.js/*`, or a needed framework capability is
3800
+ missing. Framework reports belong at <https://github.com/warlockjs/framework>.
3801
+
3802
+ ## Confirm and search first
3803
+
3804
+ 1. Reduce the problem to a minimal reproduction in a clean, generic app. Isolate
3805
+ application logic, third-party packages and configuration mistakes; a stack
3806
+ frame in the framework alone does not prove a framework bug.
3807
+ 2. Read the **installed version's** package `CHANGELOG.md` and skills. Confirm
3808
+ that the documented API exists in that version and check whether a later
3809
+ release already addresses it. For a feature, describe the missing capability
3810
+ and why the documented APIs or an app-level workaround are insufficient.
3811
+ 3. Run `warlock doctor --json` (see `warlock-doctor.md`). Fix app/environment
3812
+ findings first. If boot fails, retain only the sanitized failure; `warlock
3813
+ issue` itself does not boot the app.
3814
+ 4. Search existing reports, including closed issues, using distinctive public
3815
+ terms. If a matching issue exists, show its link and help draft a useful
3816
+ follow-up instead of opening a duplicate. Ask before posting that follow-up.
3817
+
3818
+ ```bash
3819
+ gh issue list -R warlockjs/framework --state all --search "public error or capability"
3820
+ ```
3821
+
3822
+ Without GitHub CLI, use
3823
+ <https://github.com/warlockjs/framework/issues?q=is%3Aissue> and enter those terms.
3824
+
3825
+ ## Collect and protect
3826
+
3827
+ ```bash
3828
+ warlock issue --type bug --title "Public description of the failure"
3829
+ warlock issue --type feature --title "Public description of the capability" --json
3830
+ ```
3831
+
3832
+ Collect affected package names and **installed versions**, Node and package
3833
+ manager versions, OS/architecture, TypeScript version, the reviewed `warlock
3834
+ issue` environment output, a minimal reproduction with exact steps, expected
3835
+ versus actual behavior, and relevant sanitized logs / `warlock doctor --json`
3836
+ output. If a tool cannot run or there are no relevant logs, explain why.
3837
+
3838
+ **Never paste secrets, tokens, `.env` contents, customer data, proprietary code or
3839
+ private app names** into titles, bodies, logs, screenshots, repro repositories,
3840
+ search queries or URLs. Replace the original app with a minimal generic repro.
3841
+ Review even generated environment output and stack traces; remove local paths,
3842
+ hostnames and identifying details. The command reads installed package metadata
3843
+ and a static config summary; it never reads `.env` or executes the app/config.
3844
+ Do not attach the app's full config or diagnostic report without sanitizing it.
3845
+
3846
+ ## Draft and get consent
3847
+
3848
+ Choose one template below, replace every prompt with concrete evidence, and
3849
+ write the sanitized body to a local UTF-8 file such as `framework-issue.md`.
3850
+ **Always show the complete drafted title and body to the user and explicitly ask
3851
+ before filing.** Generating a draft or URL is not consent to publish. If the user
3852
+ requests edits, show the revised draft and obtain approval for that version.
3853
+
3854
+ ### Bug body
3855
+
3856
+ ```markdown
3857
+ ### Summary
3858
+
3859
+ Public description of the framework failure and affected packages.
3860
+
3861
+ ### Environment / warlock issue output
3862
+
3863
+ Reviewed environment output: installed @warlock.js package versions, Node,
3864
+ package manager + version, OS/arch, TypeScript, static config summary.
3865
+
3866
+ ### Minimal reproduction
3867
+
3868
+ Public minimal code or repro link, setup commands and exact steps.
3869
+
3870
+ ### Expected behavior
3871
+
3872
+ What should happen, with the installed version's docs/skills reference.
3873
+
3874
+ ### Actual / current behavior
3875
+
3876
+ What happens instead, including the error and impact.
3877
+
3878
+ ### Sanitized logs / doctor output
3879
+
3880
+ Relevant logs and warlock doctor --json, or why unavailable / not applicable.
3881
+
3882
+ ### Checks
3883
+
3884
+ - [ ] Searched existing issues and checked installed-version CHANGELOG and skills.
3885
+ - [ ] Removed secrets, tokens, .env, customer data, proprietary code and private app names.
3886
+ - [ ] User reviewed this complete draft and approved filing.
3887
+ ```
3888
+
3889
+ ### Feature request body
3890
+
3891
+ ```markdown
3892
+ ### Problem / use case
3893
+
3894
+ Public description of the missing framework capability and affected packages.
3895
+
3896
+ ### Environment / warlock issue output
3897
+
3898
+ Reviewed environment output: installed @warlock.js package versions, Node,
3899
+ package manager + version, OS/arch, TypeScript, static config summary.
3900
+
3901
+ ### Minimal reproduction
3902
+
3903
+ Minimal public example of the capability that cannot currently be expressed.
3904
+
3905
+ ### Proposed behavior
3906
+
3907
+ Desired API/behavior, with an example and why it belongs in the framework.
3908
+
3909
+ ### Actual / current behavior
3910
+
3911
+ Current limitation and relevant installed-version docs/skills.
3912
+
3913
+ ### Alternatives considered
3914
+
3915
+ Existing APIs, app-level workarounds and their limitations.
3916
+
3917
+ ### Sanitized logs / doctor output
3918
+
3919
+ Relevant logs and warlock doctor --json, or why unavailable / not applicable.
3920
+
3921
+ ### Checks
3922
+
3923
+ - [ ] Searched existing issues and checked installed-version CHANGELOG and skills.
3924
+ - [ ] Removed secrets, tokens, .env, customer data, proprietary code and private app names.
3925
+ - [ ] User reviewed this complete draft and approved filing.
3926
+ ```
3927
+
3928
+ Only check a box after completing that step, including obtaining consent.
3929
+
3930
+ ## File the approved draft
3931
+
3932
+ Check `gh --version` and `gh auth status --hostname github.com`. If GitHub CLI is
3933
+ available and authenticated, **after approval** run:
3934
+
3935
+ ```bash
3936
+ gh issue create -R warlockjs/framework --title "Approved public title" --body-file framework-issue.md
3937
+ ```
3938
+
3939
+ Return the created issue's link. If GitHub CLI is unavailable or unauthenticated,
3940
+ give the user the pre-filled new-issue URL printed by `warlock issue` together
3941
+ with the approved body. The URL selects `bug.yml` or `feature.yml` and prefills
3942
+ the environment field; the user must complete the remaining form fields. URLs
3943
+ are capped at 7,500 characters and may include a truncation note: restore the
3944
+ remaining reviewed output manually. Never claim the issue was filed from merely
3945
+ printing or opening a URL. `warlock issue` never sends anything itself.
3946
+
3947
+ GitHub CLI flags: [list](https://cli.github.com/manual/gh_issue_list),
3948
+ [create](https://cli.github.com/manual/gh_issue_create),
3949
+ [authentication](https://cli.github.com/manual/gh_auth_status).
3950
+
3951
+
3748
3952
  ## request-memo `@warlock.js/core/request-memo/SKILL.md`
3749
3953
 
3750
3954
  ---
@@ -6491,7 +6695,7 @@ Client `PUT`s the bytes straight to R2 — your server never sees them.
6491
6695
 
6492
6696
  ---
6493
6697
  name: store-secrets
6494
- description: "Store app credentials with secrets.get/set/remove/has and environmentName; lazy optional OS keychain, read-only scoped environment variables, encrypted file fallback, typed SecretStoreError and memory-backed secretsFake. Use for provider keys and OAuth credentials the app must read back. Skip user passwords (hash-password) and encrypted database columns (encrypt-data)."
6698
+ description: "Store app credentials with secrets.get/set/remove/has, backend() and environmentName; lazy optional OS keychain, read-only scoped environment variables, encrypted file fallback, typed SecretStoreError and memory-backed secretsFake. Use for provider keys and OAuth credentials the app must read back. Skip user passwords (hash-password) and encrypted database columns (encrypt-data)."
6495
6699
  ---
6496
6700
 
6497
6701
  # Application secret store
@@ -6507,6 +6711,7 @@ const token = await secrets.get("vendor-token"); // string | undefined
6507
6711
  const exists = await secrets.has("vendor-token"); // boolean; true for ""
6508
6712
  const removed = await secrets.remove("vendor-token"); // boolean
6509
6713
  const variable = secrets.environmentName("vendor-token"); // variable name, not value
6714
+ const backend = await secrets.backend(); // "keychain" | "file" | "memory"; no credentials
6510
6715
 
6511
6716
  try {
6512
6717
  await secrets.remove("vendor-token");
@@ -6523,6 +6728,23 @@ Names are case-sensitive, nonempty strings of at most 256 UTF-16 code units. Val
6523
6728
 
6524
6729
  ## Configuration and backend decisions
6525
6730
 
6731
+ Use `await secrets.backend()` or `await store.backend()` to inspect active storage.
6732
+ The exported `SecretBackendType` is `"keychain" | "file" | "memory"`. Inspection
6733
+ triggers core's own lazy selection and shares the memoized keychain probe with
6734
+ credential operations, including concurrent calls; never run an independent probe.
6735
+ It returns the selected backend, not the source of an individual secret. Scoped
6736
+ environment reads do not change it. File selection does not create files or verify
6737
+ the encryption key/filesystem. A later locked keychain remains `"keychain"` and
6738
+ credential operations fail safely instead of silently changing selection.
6739
+
6740
+ Resolved `secrets.driver` overrides `SECRETS_DRIVER`: memory reports `"memory"`;
6741
+ auto reports `"keychain"` after a successful initial probe or `"file"` after failure.
6742
+ `secretsFake` and explicit `MemorySecretBackend` report `"memory"` without probing.
6743
+ Explicit backends bypass driver configuration. Custom `SecretBackend` implementations
6744
+ may declare readonly `type: SecretBackendType`; omitted metadata reports `"memory"`
6745
+ for compatibility with isolated injected test backends. Core file/keychain instances
6746
+ declare their own type.
6747
+
6526
6748
  - Default namespace: app name plus the SHA-256 hash of the absolute project root. For changing release directories, configure a stable unique namespace including the deployment environment.
6527
6749
  - Reads: OS keychain → exact scoped environment variable → encrypted file.
6528
6750
  - Optional peer: `npm install @napi-rs/keyring`. Core lazily uses its 2.1.1 `AsyncEntry` API. Linux requires `secret-service` for persistence; it does not use the memory-only keyutils fallback. Sources: [official README](https://github.com/Brooooooklyn/keyring-node#readme), [published declarations](https://www.npmjs.com/package/@napi-rs/keyring?activeTab=code), verified 2026-10-19.
@@ -6575,6 +6797,7 @@ import type { SecretBackend, SecretStoreOptions } from "@warlock.js/core/secrets
6575
6797
  const backend: SecretBackend = new MemorySecretBackend();
6576
6798
  const options: SecretStoreOptions = { namespace: "test-app", backend };
6577
6799
  const store = new SecretStore(options);
6800
+ await store.backend(); // "memory"
6578
6801
  await store.set("vendor-token", "test-credential");
6579
6802
  await store.get("vendor-token");
6580
6803
  await store.has("vendor-token");
@@ -11300,7 +11523,7 @@ const types = runTypecheck({ files: ["src/app/posts/services/publish.service.ts"
11300
11523
 
11301
11524
  ## See also
11302
11525
 
11303
- - `report-framework-issue.md` — confirm a framework bug or missing capability, collect `warlock issue` output, and get the user's approval before filing.
11526
+ - the `report-framework-issue` topic — confirm a framework bug or missing capability, collect `warlock issue` output, and get the user's approval before filing.
11304
11527
  - The `warlock-doctor` topic — boot-time diagnostics; `doctor --json` uses the same codes and fields.
11305
11528
  - The `warlock-inspect` topic — the app's routes, models and config as JSON.
11306
11529
  - The `warlock-conventions` topic — the rules behind `WL9001`–`WL9012`, with the fix for each.
@@ -12551,7 +12774,7 @@ CLI commands, scheduled jobs, queue workers — anything running outside an HTTP
12551
12774
 
12552
12775
  ---
12553
12776
  name: write-cli-command
12554
- description: 'Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.register.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.register.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — the `run-app` topic; warlock.config.ts wiring — the `configure-app` topic; competing libs `commander`, `yargs`, `oclif`.'
12777
+ description: 'Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.setup.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.setup.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — the `run-app` topic; warlock.config.ts wiring — the `configure-app` topic; competing libs `commander`, `yargs`, `oclif`.'
12555
12778
  ---
12556
12779
 
12557
12780
  # Warlock — write a CLI command
@@ -12781,7 +13004,11 @@ Run `warlock add --list` to see what's currently registered. Pass `--packageMana
12781
13004
  is loaded automatically by `warlock dev` when installed, and is omitted from a
12782
13005
  production install with dev dependencies excluded.
12783
13006
 
12784
- The Web starter keeps the page's universal non-component setup in `src/web/index.register.ts`, while `src/web/index.page.tsx` re-exports `register`. Warlock still discovers and runs the hook from the page namespace in both SSR and the browser, but editing the page component remains inside React's Fast Refresh boundary. Do not move the `register()` declaration inline beside the component: React Refresh treats that non-component export as incompatible and reloads the page, losing component state.
13007
+ `warlock add web` creates `root.tsx` + `root.setup.ts` and `index.page.tsx` +
13008
+ `index.setup.ts`. Setup files own configuration and universal `register()`
13009
+ logic; UI files own components. Warlock composes the pairs on the server and
13010
+ projects browser-safe registration to the client, preserving the component
13011
+ Fast Refresh boundary.
12785
13012
 
12786
13013
  ### AI input measurement
12787
13014
 
package/llms.txt CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  ## Skills
8
8
 
9
+ - [Package orientation](@warlock.js/core/skills/index.md): The Warlock server framework: HTTP routes, controllers, responses, resources, repositories, CLI, mail, storage, security helpers. Exports `router`, `Request`, `Response`, `RequestHandler`, `useCase`, `RepositoryManager`, `defineResource`, `defineConfig`, `storage`, `sendMail`, `hashPassword`, `command`. Use for: add a route, write a controller, return a JSON response, hide a field from the response, upload a file, send an email, hash a password, add a CLI command, generate an OpenAPI document, type an API response, wire a socket, run or configure the app. Not this package: database models/queries → @warlock.js/cascade; input schemas → @warlock.js/seal; SSR pages → @warlock.js/web.
9
10
  - [add-connector](@warlock.js/core/add-connector/SKILL.md): Extend Warlock with a `BaseConnector` subclass and register its instance in `warlock.config.ts > connectors`. Covers runtime lifecycle (`boot`, `start`, `shutdown`, priority, phase, watched files) and the optional static `build.generate` / `build.emit` contribution used by `warlock build`. Triggers: `BaseConnector`, `connectors`, `ConnectorLifecyclePhase`, `ConnectorBuildContribution`, `build.generate`, `build.emit`; "add a queue worker", "wire a subsystem into bootstrap", "contribute files to warlock build", "control startup ordering", "graceful shutdown hook". Skip: app context accessors — the `use-app-context` topic; general config shape — the `configure-app` topic; competing pattern: hand-rolled process signal blocks, NestJS lifecycle hooks.
10
11
  - [benchmark-code](@warlock.js/core/benchmark-code/SKILL.md): Wrap a function with `measure(name, fn, options?)` to time it and classify the latency — onComplete/onError/onFinish hooks, `latencyRange` thresholds, `BenchmarkProfiler` for percentiles, `BenchmarkSnapshots` for raw captures. Triggers: `measure`, `BenchmarkProfiler`, `BenchmarkSnapshots`, `BenchmarkChannel`, `ConsoleChannel`, `latencyRange`, `shouldBenchmarkError`; "time this operation", "profile a slow service", "emit p50/p95/p99 metrics", "classify latency against thresholds"; typical import `import { measure, BenchmarkProfiler } from "@warlock.js/core"`. Skip: retry composition — the `retry-operation` topic; benchmark config wiring — the `configure-app` topic; competing libs `prom-client`, `pino`, `perf_hooks`, `console.time`.
11
12
  - [build-restful](@warlock.js/core/build-restful/SKILL.md): Generate standard CRUD endpoints — via `router.route(path).list().show().create().update().destroy()` chain or the `Restful` base class. Pick the chain by default; reach for `Restful` when you want repository-bound defaults. Triggers: `router.route`, `Restful`, `router.restfulResource`, `RouteResource`, `.crud`, `.nest`, `beforeCreate`, `onCreate`; "build a CRUD API", "register list/show/create/update/destroy", "repository-bound default handlers", "override a single REST action"; typical import `import { router, Restful } from "@warlock.js/core"`. Skip: wider router surface — the `register-route` topic; per-action controllers — the `create-controller` topic; wire mapping — the `define-resource` topic; competing pattern: hand-rolled controllers, `@nestjs/swagger` decorator-driven CRUD.
@@ -23,6 +24,7 @@
23
24
  - [model-factories](@warlock.js/core/model-factories/SKILL.md): Deterministic model factories for tests and seeders — `defineFactory(Model, (seed) => attributes)` with `make()`, `makeMany(n)`, `create()`, `create(n)`, `createMany(n)`, named states via `.state()` / `.with()`, and a faker-free seed (`seed.text`, `seed.email`, `seed.uuid`, `seed.date`, `seed.number`, `seed.pick`). Triggers: `defineFactory`, `Factory`, `FactorySeed`, `resetFactorySequences`, `userFactory`; "test fixtures", "create test users", "factory states", "deterministic test data", "build a request body for a test". Typical import `import { defineFactory } from "@warlock.js/core/tests"`. Skip: seeding a real database for development — the `write-seeder` topic; fakes — the `test-fakes` topic.
24
25
  - [process-image](@warlock.js/core/process-image/SKILL.md): Transform images with the `Image` class — resize, crop, rotate, format, quality, watermark, blur, etc. — using a deferred pipeline that runs only at `save()` / `toBuffer()` / `toBase64()` / `toDataUrl()` time. Requires sharp via `warlock add image`. Triggers: `Image`, `Image.fromFile`, `Image.fromBuffer`, `Image.fromUrl`, `.resize`, `.crop`, `.watermark`, `.toBuffer`, `.toDataUrl`, `.apply`; "resize an image", "generate a thumbnail", "watermark a product photo", "build an image pipeline"; typical import `import { Image } from "@warlock.js/core"`. Skip: multipart upload entry — the `upload-file` topic; storage persistence — the `store-file` topic; competing libs `sharp` direct, `jimp`, `imagemagick`, `gm`.
25
26
  - [register-route](@warlock.js/core/register-route/SKILL.md): Register HTTP routes via @warlock.js/core's router — single routes, prefix groups, middleware-guarded blocks, and RESTful resource chains. Routes always live in `src/app/<module>/routes.ts`. Triggers: `router.get`, `router.post`, `router.prefix`, `router.group`, `router.route`, `guarded`; "add a route", "wire a controller to a URL", "group routes by prefix", "register a RESTful resource"; typical import `import { router } from "@warlock.js/core"`. Skip: handler shape — the `create-controller` topic; CRUD chain details — the `build-restful` topic; middleware authoring — the `write-middleware` topic; competing libs `express`, `fastify`, `koa`, `@nestjs/common`.
27
+ - [report-framework-issue](@warlock.js/core/report-framework-issue/SKILL.md): Report a confirmed Warlock.js framework bug or missing capability. Read when behavior contradicts the installed docs, a crash appears to originate in @warlock.js packages, or no documented API meets a requirement; covers minimal reproduction, duplicate searches, sanitized warlock issue output and user approval before filing.
26
28
  - [request-memo](@warlock.js/core/request-memo/SKILL.md): Memoize async work for one HTTP request with `requestMemo<T>(key, fn)` — the v5 replacement for removed `fromRequest`, with single-flight promise sharing, settled-success reuse, rejection eviction, and no cross-request fallback. Triggers: `requestMemo`, `fromRequest`, `fromRequest removed`, `request-scoped cache`, `single-flight`, `current request memo`; "migrate off fromRequest", "load this once per request", "deduplicate concurrent loaders", "cache a repository lookup during one request"; typical import `import { requestMemo } from "@warlock.js/core"`. Skip: middleware-written request state — the `use-request-locals` topic; process-wide or cross-request caching — the `use-middleware` topic; competing patterns: dynamic `request[key]` properties, module-global `Map`, payload `request.get()` / `request.set()`.
27
29
  - [request-tracing](@warlock.js/core/request-tracing/SKILL.md): Vendor-neutral request tracing hooks (`http.tracing`) — observe request start/end and named phase spans (`route.match`, `middleware`, `validation`, `handler`, `response.write`) without adopting an OTel/vendor dependency in `core`. Covers the `TracingHooks` shape, trace id derivation from an inbound W3C `traceparent` vs `request.id`, that a throwing hook is caught and reported once (never breaks the request), and zero overhead when disabled. Triggers: `http.tracing`, `TracingHooks`, `onRequestStart`, `onRequestEnd`, `onPhase`, `traceparent`, `traceId`, `dispatchPhase`, "instrument requests", "trace a request", "slow phase logging", "APM / OTel bridge for Warlock". Skip: request-id header echo/inheritance (`X-Request-Id`) — the `use-middleware` topic; app-level structured logging — the `logger-basics` topic of the `warlock-js-logger` skill; competing libs `@opentelemetry/api` direct instrumentation, `express-request-id`, hand-rolled `X-Trace-Id` middleware.
28
30
  - [resolve-path](@warlock.js/core/resolve-path/SKILL.md): Path helpers anchored at `process.cwd()` — `rootPath`, `srcPath`, `appPath`, `configPath`, `publicPath`, `storagePath`, `uploadsPath`, `cachePath`, `logsPath`, `tempPath`, `warlockPath`, `sanitizePath`. Optional `uploads.root` config overrides the uploads anchor. Triggers: `appPath`, `configPath`, `uploadsPath`, `storagePath`, `publicPath`, `cachePath`, `logsPath`, `tempPath`, `sanitizePath`, `paths`; "resolve a path inside src/app", "absolute upload destination", "sanitize a user filename", "ship uploads to a mounted volume"; typical import `import { appPath, uploadsPath } from "@warlock.js/core"`. Skip: HTTP URL helpers — the `build-url` topic; app metadata — the `use-app-context` topic; storage abstraction — the `store-file` topic; competing patterns: `path.join(process.cwd(), ...)`, hand-rolled directory constants.
@@ -31,7 +33,7 @@
31
33
  - [send-mail](@warlock.js/core/send-mail/SKILL.md): Send transactional email — `Mail` fluent builder, `sendMail()` direct call, React Email components. Test mode auto-captures into an in-memory mailbox; dev mode logs. Triggers: `Mail.to`, `sendMail`, `setMailMode`, `mailEvents`, `assertMailSent`, `getTestMailbox`, `wasMailSentTo`, `closeAllMailers`; "send a transactional email", "build a React Email template", "configure SMTP or SES", "assert an email was sent in tests"; typical import `import { Mail, sendMail } from "@warlock.js/core"`. Skip: per-config wiring — the `configure-app` topic; layered service patterns — the `warlock-conventions` topic; competing libs `nodemailer` direct, `@sendgrid/mail`, `resend`, `mailgun.js`.
32
34
  - [send-response](@warlock.js/core/send-response/SKILL.md): Send HTTP responses via @warlock.js/core's Response helpers — success/error variants, status helpers, redirects, files, streams, and SSE. Picking the right helper carries the HTTP semantic without manual status codes. Triggers: `response.success`, `response.successCreate`, `response.notFound`, `response.forbidden`, `response.badRequest`, `response.sendFile`, `response.stream`, `response.sse`, `response.replay`, `retainEvents`, `retainChunks`, `backpressure`, `@warlock.js/core/errors`, `ResourceNotFoundError`, `ForbiddenError`, `request.cookie`, `request.hasCookie`, `CookieJarUnavailableError`; "return a 201 from a controller", "send a file", "stream Server-Sent Events", "throw HTTP-shaped errors from services"; typical import `import type { RequestHandler, Response } from "@warlock.js/core"`. Skip: controller shape — the `create-controller` topic; route registration — the `register-route` topic; competing patterns: hand-rolled status codes via `reply.code(404).send(...)`, raw Fastify reply.
33
35
  - [store-file](@warlock.js/core/store-file/SKILL.md): Read/write/delete files via the `storage` singleton — disks, drivers (local/S3/R2/DO Spaces), `storage.use(name)`, `StorageFile` handles, presigned URLs. Triggers: `storage.put`, `storage.get`, `storage.use`, `StorageFile`, `storageConfigurations`, `getPresignedUrl`, `getPresignedUploadUrl`; "save an uploaded file", "switch between local and S3", "generate a presigned URL", "read file metadata"; typical import `import { storage } from "@warlock.js/core"`. Skip: multipart parsing + image chain — the `upload-file` topic; image transforms — the `process-image` topic; storage config shape — the `configure-app` topic; competing libs `@aws-sdk/client-s3`, `multer`, `formidable`.
34
- - [store-secrets](@warlock.js/core/store-secrets/SKILL.md): Store app credentials with secrets.get/set/remove/has and environmentName; lazy optional OS keychain, read-only scoped environment variables, encrypted file fallback, typed SecretStoreError and memory-backed secretsFake. Use for provider keys and OAuth credentials the app must read back. Skip user passwords (hash-password) and encrypted database columns (encrypt-data).
36
+ - [store-secrets](@warlock.js/core/store-secrets/SKILL.md): Store app credentials with secrets.get/set/remove/has, backend() and environmentName; lazy optional OS keychain, read-only scoped environment variables, encrypted file fallback, typed SecretStoreError and memory-backed secretsFake. Use for provider keys and OAuth credentials the app must read back. Skip user passwords (hash-password) and encrypted database columns (encrypt-data).
35
37
  - [test-browser](@warlock.js/core/test-browser/SKILL.md): Write or repair browser e2e specs using warlock e2e and @warlock.js/core/e2e, with owned app fixtures, direct CDP interaction, responsive screenshots and run evidence. Use for real browser flows, click races or viewport overflow; use test-http for API-only tests.
36
38
  - [test-fakes](@warlock.js/core/test-fakes/SKILL.md): The test fakes Warlock installs by default in the test environment — `mailFake`, `queueFake`, `cacheFake`, `storageFake`, `clockFake`, `idsFake`, `secretsFake` — and their assertions (`assertSent`, `assertPushed`, `assertHas`, `assertExists`, `travel`), plus how to opt out (`tests.fakes`, `setupTest({ fakes })`). Triggers: `mailFake`, `queueFake`, `cacheFake`, `storageFake`, `clockFake`, `idsFake`, `secretsFake`, `installTestFakes`, `restoreTestFakes`, `tests.fakes`, `FakeAssertionError`, `clock.now`, `ids.uuid`, `setDispatchInterceptor`; "assert an email was sent", "assert a job was dispatched", "freeze time in a test", "deterministic ids", "tests without Redis", "keep the real cache driver in tests". Typical import `import { mailFake, queueFake } from "@warlock.js/core/tests"`. Skip: HTTP request helpers — the `test-http` topic; fixtures — the `model-factories` topic.
37
39
  - [test-http](@warlock.js/core/test-http/SKILL.md): Integration tests against a real HTTP server — `startHttpTestServer()` boots one shared server in globalSetup, then `testGet` / `testPost` / `expectJson` make typed requests against it. Triggers: `startHttpTestServer`, `startHttpTestServer({ port })`, `startHttpTestServer({ port: 0 })`, `stopHttpTestServer`, `createTestHttpServer`, `TestHttpServer`, `createTestRequestClient`, `snapshotResponse`, `actingAs`, `AuthenticatedTestClient`, `testGet`, `testPost`, `testPut`, `testPatch`, `testDelete`, `expectJson`, `getTestServerUrl`, `testRequest`, `PortInUseError`, `assertPortIsAvailable`, `isPortAvailable`; "integration-test a controller", "end-to-end HTTP test", "globalSetup HTTP server", "assert status and body shape", "test server port already in use", "EADDRINUSE while running tests", "run tests while the dev server is up", "ephemeral test port", "test with the real Fastify plugins", "assert mail sent by a request", "response snapshot"; typical import `import { testGet, testPost, expectJson } from "@warlock.js/core/tests"`. Skip: pure unit tests — the `test-service` topic; controller shape — the `create-controller` topic; competing libs `supertest`, `light-my-request`, `nock`.
@@ -56,7 +58,7 @@
56
58
  - [warlock-routes](@warlock.js/core/warlock-routes/SKILL.md): Run `warlock routes` — a read-only command that lists the registered HTTP routes as a verb-colored table (method / path / name / action / middleware-count / source), a sibling of `warlock doctor`. Filter with `--method` / `--path` / `--name`, or emit normalized rows as JSON with `--json`. Also covers `warlock routes:diff`, which compares live page routes against the last `warlock build`'s route snapshot and exits non-zero on drift. Triggers: `warlock routes`, `routesCommand`, `warlock routes:diff`, `routesDiffCommand`, "list my routes", "show all routes", "route table", "what endpoints does my app expose", "dump routes as JSON", "which routes have middleware", "route map for CI", "did my page routes drift from the last build"; run as `npx warlock routes` / `npx warlock routes:diff`. Skip: read-only health/preflight checks — the `warlock-doctor` topic; defining/naming/grouping routes — the `register-route` topic; authoring a general CLI command — the `write-cli-command` topic; competing tools `nest`/`express` route listers, `php artisan route:list`.
57
59
  - [warlock-trace](@warlock.js/core/warlock-trace/SKILL.md): Verify runtime behaviour without a browser: `warlock trace <method> <url> [--body json|@file] [--header k:v] [--json]` sends one request to the running `warlock dev` server and prints what devtools recorded for it — middleware chain with timings, validation result and errors, handler time, queries with N+1 flags, logs, cache operations, captured mails, the response and timings — as a versioned report (`schemaVersion: 1`); `traceRequest()` returns the same object. Triggers: `warlock trace`, `traceRequest`, `TraceReport`, `buildTraceReport`, `x-request-id`, `.warlock/dev-server.json`, `WL8008`, `WL8009`, `WL5004`, `--id-header`; "did validation pass for this request", "which queries does this endpoint run", "is there an N+1 on this route", "what middleware runs on this route", "check the endpoint after my change", "request timeline as JSON". Skip: the devtools dashboard in a browser — the `devtools-overview` skill of @warlock.js/devtools; static route facts (guard, rate limit, schemas) — the `warlock-inspect` topic; typecheck/lint/tests — the `warlock-check` topic.
58
60
  - [wire-socket](@warlock.js/core/wire-socket/SKILL.md): Configure Socket.IO via `src/config/socket.ts`, reach the live server through `getSocketServer()` (or `app.socket` post-bootstrap), register `connection` handlers once the late-phase socket connector has booted, emit from controllers/services, use rooms and namespaces. Triggers: `app.socket`, `getSocketServer`, `SocketOptions`, `socket.io` `Server`, `socket.join`, `socket.to`, `io.of`, `io.use`; "add realtime chat", "emit socket events from a service", "use rooms and namespaces", "per-socket JWT auth". Skip: connector lifecycle — the `add-connector` topic; app context accessors — the `use-app-context` topic; competing libs `ws`, `socket.io` direct without Warlock connector, `uWebSockets.js`.
59
- - [write-cli-command](@warlock.js/core/write-cli-command/SKILL.md): Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.register.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.register.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — the `run-app` topic; warlock.config.ts wiring — the `configure-app` topic; competing libs `commander`, `yargs`, `oclif`.
61
+ - [write-cli-command](@warlock.js/core/write-cli-command/SKILL.md): Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.setup.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.setup.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — the `run-app` topic; warlock.config.ts wiring — the `configure-app` topic; competing libs `commander`, `yargs`, `oclif`.
60
62
  - [write-middleware](@warlock.js/core/write-middleware/SKILL.md): Author HTTP middleware for @warlock.js/core — the `({ request, response })` signature, short-circuit by returning a response, enrich the request with extra fields, register per-route, per-group, or app-wide. Triggers: `Middleware`, `MiddlewareResponse`, `router.group`, `guarded`, `request.detectIp`, `authMiddleware`; "write a custom middleware", "short-circuit a request", "enrich the request with extra fields", "per-route vs per-group middleware"; typical import `import type { Middleware } from "@warlock.js/core"`. Skip: built-in middleware catalog — the `use-middleware` topic; route attachment — the `register-route` topic; response helpers — the `send-response` topic; competing patterns: `express` `(req, res, next)` middleware, Fastify `preHandler` hooks.
61
63
  - [write-seeder](@warlock.js/core/write-seeder/SKILL.md): Author a seed file under `src/app/<module>/seeds/<name>.ts` using the `seeder()` factory — `name`, `dependsOn`, `once`, `order`, `batchSize`, `run({ track, now, batchSize })`. Auto-discovered by `warlock seed`; tracked in a `seeds` table; per-record refs in `seed_records` so `warlock seed --drop` can undo a seed. Triggers: `seeder`, `Seeder`, `SeedResult`, `SeedContext`, `SeedClock`, `track`, `now`, `batchSize`, `SeedersManager`, `warlock seed`, `--fresh`, `--drop`, `--list`, `--path`; "seed default roles", "undo a seed", "one-time data migration", "auto-discovered seeds", "order seeds by dependency", "deterministic seed timestamps", "inject a seed clock"; typical import `import { seeder } from "@warlock.js/core"`. Skip: module folder layout — the `create-module` topic; repository CRUD — the `use-repository` topic; CLI flags — the `write-cli-command` topic; competing patterns: hand-rolled `node scripts/seed.js`, `typeorm-seeding`.
62
64
  - [write-use-case](@warlock.js/core/write-use-case/SKILL.md): Author `useCase()` pipelines for business logic — guards, schema, before/after middleware, retry, benchmark, broadcast, lifecycle callbacks; transport-agnostic and observable by default. Input is inferred from the `schema`. Triggers: `useCase`, `UseCaseContext`, `UseCaseResult`, `retry`, `benchmark`, `broadcast`, `description`, `globalUseCasesEvents`, `UseCaseBroadcastChannel`; "encapsulate a business operation", "share logic between HTTP and CLI", "add guards and lifecycle hooks", "broadcast a use case result", "transport-agnostic pipeline"; typical import `import { useCase } from "@warlock.js/core"`. Skip: thin handler shape — the `create-controller` topic; schema details — the `validate-input` topic; the standalone retry util — the `retry-operation` topic; competing libs `@nestjs/cqrs`, `inversify`, hand-rolled service classes.
package/package.json CHANGED
@@ -25,12 +25,12 @@
25
25
  "@mongez/slug": "^1.0.7",
26
26
  "@mongez/supportive-is": "^3.0.0",
27
27
  "@mongez/time-wizard": "^1.0.6",
28
- "@warlock.js/cache": "5.34.0",
29
- "@warlock.js/cascade": "5.34.0",
30
- "@warlock.js/context": "5.34.0",
31
- "@warlock.js/fs": "5.34.0",
32
- "@warlock.js/logger": "5.34.0",
33
- "@warlock.js/seal": "5.34.0",
28
+ "@warlock.js/cache": "5.34.2",
29
+ "@warlock.js/cascade": "5.34.2",
30
+ "@warlock.js/context": "5.34.2",
31
+ "@warlock.js/fs": "5.34.2",
32
+ "@warlock.js/logger": "5.34.2",
33
+ "@warlock.js/seal": "5.34.2",
34
34
  "bcryptjs": "^3.0.3",
35
35
  "chokidar": "^5.0.0",
36
36
  "dayjs": "^1.11.19",
@@ -55,12 +55,12 @@
55
55
  "@aws-sdk/lib-storage": "^3.955.0",
56
56
  "@aws-sdk/s3-request-presigner": "^3.955.0",
57
57
  "@react-email/render": "^2.0.5",
58
- "@warlock.js/access": "5.34.0",
59
- "@warlock.js/ai": "5.34.0",
60
- "@warlock.js/ai-tools": "5.34.0",
61
- "@warlock.js/devtools": "5.34.0",
62
- "@warlock.js/herald": "5.34.0",
63
- "@warlock.js/notifications": "5.34.0",
58
+ "@warlock.js/access": "5.34.2",
59
+ "@warlock.js/ai": "5.34.2",
60
+ "@warlock.js/ai-tools": "5.34.2",
61
+ "@warlock.js/devtools": "5.34.2",
62
+ "@warlock.js/herald": "5.34.2",
63
+ "@warlock.js/notifications": "5.34.2",
64
64
  "nodemailer": "^8.0.5",
65
65
  "react": "^19.2.3",
66
66
  "react-dom": "^19.2.3",
@@ -145,7 +145,7 @@
145
145
  "engines": {
146
146
  "node": ">=22.15"
147
147
  },
148
- "version": "5.34.0",
148
+ "version": "5.34.2",
149
149
  "type": "module",
150
150
  "main": "./esm/index.mjs",
151
151
  "module": "./esm/index.mjs",
package/skills/index.md CHANGED
@@ -14,11 +14,11 @@ Core is the application runtime: it boots the app, auto-loads each module's spec
14
14
  4. Return via `response.*` (`send-response.md`) and shape output with a resource (`define-resource.md`); declare `responseSchema` for typed clients and docs (`create-controller.md`, `generate-openapi.md`).
15
15
  5. Configure and run (`configure-app.md`, `run-app.md`); check setup with `warlock-doctor.md`, read the app with `warlock-inspect.md` (or serve it to an agent with `warlock-mcp.md`), verify a change with `warlock-check.md`, and a request's runtime behaviour with `warlock-trace.md`.
16
16
 
17
- When the framework is wrong or missing a capability, follow `report-framework-issue.md` to prepare a public report and ask the user before filing.
17
+ When the framework is wrong or missing a capability, follow the `report-framework-issue` topic to prepare a public report and ask the user before filing.
18
18
 
19
19
  ## Topics by area
20
20
 
21
- - **Foundations:** warlock-conventions, create-module, make-endpoint, configure-app, use-app-context, resolve-path, build-url, update-packages, lower-stage3-decorators
21
+ - **Foundations:** warlock-conventions, create-module, make-endpoint, configure-app, use-app-context, resolve-path, build-url, update-packages, lower-stage3-decorators, upgrade-from-5-29
22
22
  - **HTTP & routing:** register-route, warlock-routes, create-controller, use-middleware, write-middleware, validate-input, use-request-locals, build-restful, wire-socket
23
23
  - **Responses & resources:** send-response, define-resource, use-model-transformers, use-localization
24
24
  - **Domain layers:** write-use-case, use-repository, write-seeder
@@ -26,7 +26,7 @@ When the framework is wrong or missing a capability, follow `report-framework-is
26
26
  - **Agent tooling:** warlock-mcp, warlock-trace, warlock-agents-md, warlock-board
27
27
  - **Storage, files & mail:** store-file, upload-file, process-image, send-mail
28
28
  - **Security & utilities:** hash-password, encrypt-data, store-secrets, retry-operation, benchmark-code, request-memo, request-tracing
29
- - **Testing:** test-http, test-service, test-fakes, model-factories
29
+ - **Testing:** test-browser, test-http, test-service, test-fakes, model-factories
30
30
 
31
31
  ## Conventions and pitfalls
32
32
 
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: report-framework-issue
3
+ description: "Report a confirmed Warlock.js framework bug or missing capability. Read when behavior contradicts the installed docs, a crash appears to originate in @warlock.js packages, or no documented API meets a requirement; covers minimal reproduction, duplicate searches, sanitized warlock issue output and user approval before filing."
4
+ ---
5
+
1
6
  # Report a Warlock.js framework issue
2
7
 
3
8
  Use this topic when behavior contradicts the installed version's docs or skills,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: store-secrets
3
- description: "Store app credentials with secrets.get/set/remove/has and environmentName; lazy optional OS keychain, read-only scoped environment variables, encrypted file fallback, typed SecretStoreError and memory-backed secretsFake. Use for provider keys and OAuth credentials the app must read back. Skip user passwords (hash-password) and encrypted database columns (encrypt-data)."
3
+ description: "Store app credentials with secrets.get/set/remove/has, backend() and environmentName; lazy optional OS keychain, read-only scoped environment variables, encrypted file fallback, typed SecretStoreError and memory-backed secretsFake. Use for provider keys and OAuth credentials the app must read back. Skip user passwords (hash-password) and encrypted database columns (encrypt-data)."
4
4
  ---
5
5
 
6
6
  # Application secret store
@@ -16,6 +16,7 @@ const token = await secrets.get("vendor-token"); // string | undefined
16
16
  const exists = await secrets.has("vendor-token"); // boolean; true for ""
17
17
  const removed = await secrets.remove("vendor-token"); // boolean
18
18
  const variable = secrets.environmentName("vendor-token"); // variable name, not value
19
+ const backend = await secrets.backend(); // "keychain" | "file" | "memory"; no credentials
19
20
 
20
21
  try {
21
22
  await secrets.remove("vendor-token");
@@ -32,6 +33,23 @@ Names are case-sensitive, nonempty strings of at most 256 UTF-16 code units. Val
32
33
 
33
34
  ## Configuration and backend decisions
34
35
 
36
+ Use `await secrets.backend()` or `await store.backend()` to inspect active storage.
37
+ The exported `SecretBackendType` is `"keychain" | "file" | "memory"`. Inspection
38
+ triggers core's own lazy selection and shares the memoized keychain probe with
39
+ credential operations, including concurrent calls; never run an independent probe.
40
+ It returns the selected backend, not the source of an individual secret. Scoped
41
+ environment reads do not change it. File selection does not create files or verify
42
+ the encryption key/filesystem. A later locked keychain remains `"keychain"` and
43
+ credential operations fail safely instead of silently changing selection.
44
+
45
+ Resolved `secrets.driver` overrides `SECRETS_DRIVER`: memory reports `"memory"`;
46
+ auto reports `"keychain"` after a successful initial probe or `"file"` after failure.
47
+ `secretsFake` and explicit `MemorySecretBackend` report `"memory"` without probing.
48
+ Explicit backends bypass driver configuration. Custom `SecretBackend` implementations
49
+ may declare readonly `type: SecretBackendType`; omitted metadata reports `"memory"`
50
+ for compatibility with isolated injected test backends. Core file/keychain instances
51
+ declare their own type.
52
+
35
53
  - Default namespace: app name plus the SHA-256 hash of the absolute project root. For changing release directories, configure a stable unique namespace including the deployment environment.
36
54
  - Reads: OS keychain → exact scoped environment variable → encrypted file.
37
55
  - Optional peer: `npm install @napi-rs/keyring`. Core lazily uses its 2.1.1 `AsyncEntry` API. Linux requires `secret-service` for persistence; it does not use the memory-only keyutils fallback. Sources: [official README](https://github.com/Brooooooklyn/keyring-node#readme), [published declarations](https://www.npmjs.com/package/@napi-rs/keyring?activeTab=code), verified 2026-10-19.
@@ -84,6 +102,7 @@ import type { SecretBackend, SecretStoreOptions } from "@warlock.js/core/secrets
84
102
  const backend: SecretBackend = new MemorySecretBackend();
85
103
  const options: SecretStoreOptions = { namespace: "test-app", backend };
86
104
  const store = new SecretStore(options);
105
+ await store.backend(); // "memory"
87
106
  await store.set("vendor-token", "test-credential");
88
107
  await store.get("vendor-token");
89
108
  await store.has("vendor-token");
@@ -127,7 +127,7 @@ const types = runTypecheck({ files: ["src/app/posts/services/publish.service.ts"
127
127
 
128
128
  ## See also
129
129
 
130
- - `report-framework-issue.md` — confirm a framework bug or missing capability, collect `warlock issue` output, and get the user's approval before filing.
130
+ - the `report-framework-issue` topic — confirm a framework bug or missing capability, collect `warlock issue` output, and get the user's approval before filing.
131
131
  - The `warlock-doctor` topic — boot-time diagnostics; `doctor --json` uses the same codes and fields.
132
132
  - The `warlock-inspect` topic — the app's routes, models and config as JSON.
133
133
  - The `warlock-conventions` topic — the rules behind `WL9001`–`WL9012`, with the fix for each.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: write-cli-command
3
- description: 'Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.register.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.register.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — the `run-app` topic; warlock.config.ts wiring — the `configure-app` topic; competing libs `commander`, `yargs`, `oclif`.'
3
+ description: 'Author a custom `warlock <my-cmd>` command via the `command()` factory — name, description, action, options, preload, then register in `warlock.config.ts > cli.commands` or drop in `src/app/<module>/commands/`. Also covers built-in `warlock add` feature scaffolding, including the Web starter and `index.setup.ts`. Triggers: `command`, `CLICommand`, `CLICommandPreload`, `CLICommandOption`, `preload`, `preAction`, `persistent`, `colors`, `warlock add`, `warlock add bull-board`, `index.setup.ts`; "write a custom warlock command", "one-off maintenance task", "ship a CLI from a package", "framework built-in commands"; typical import `import { command } from "@warlock.js/core"`. Skip: framework dev/build/start — the `run-app` topic; warlock.config.ts wiring — the `configure-app` topic; competing libs `commander`, `yargs`, `oclif`.'
4
4
  ---
5
5
 
6
6
  # Warlock — write a CLI command
@@ -230,7 +230,11 @@ Run `warlock add --list` to see what's currently registered. Pass `--packageMana
230
230
  is loaded automatically by `warlock dev` when installed, and is omitted from a
231
231
  production install with dev dependencies excluded.
232
232
 
233
- The Web starter keeps the page's universal non-component setup in `src/web/index.register.ts`, while `src/web/index.page.tsx` re-exports `register`. Warlock still discovers and runs the hook from the page namespace in both SSR and the browser, but editing the page component remains inside React's Fast Refresh boundary. Do not move the `register()` declaration inline beside the component: React Refresh treats that non-component export as incompatible and reloads the page, losing component state.
233
+ `warlock add web` creates `root.tsx` + `root.setup.ts` and `index.page.tsx` +
234
+ `index.setup.ts`. Setup files own configuration and universal `register()`
235
+ logic; UI files own components. Warlock composes the pairs on the server and
236
+ projects browser-safe registration to the client, preserving the component
237
+ Fast Refresh boundary.
234
238
 
235
239
  ### AI input measurement
236
240
 
package/skills/README.md DELETED
@@ -1,76 +0,0 @@
1
- # @warlock.js/core — skills index
2
-
3
- Each folder holds one `SKILL.md` (an agent-facing how-to for a single task). The `llms.txt` / `llms-full.txt` at the package root are **generated projections** of this folder — run `node scripts/generate-llms.mjs` from the package root after any skill change; never hand-edit them.
4
-
5
- ## HTTP layer
6
-
7
- - `register-route` — register single routes, prefix groups, middleware-guarded blocks, and RESTful resource chains.
8
- - `build-restful` — generate standard CRUD endpoints via the `router.route(...)` chain or the `Restful` base class.
9
- - `create-controller` — author HTTP controllers: `RequestHandler` signature, validated input, response helpers, middleware, `responseSchema` response types.
10
- - `send-response` — `Response` helpers: success/error variants, status helpers, redirects, files, streams, SSE.
11
- - `validate-input` — author seal schemas, attach them to controllers, infer types, layer DTOs.
12
- - `use-middleware` — attach built-in HTTP middleware (rateLimit, concurrencyLimit, maxBodySize, …) via the `middleware` namespace.
13
- - `write-middleware` — author HTTP middleware: the `({ request, response })` signature, short-circuit, request enrichment.
14
- - `build-url` — HTTP URL helpers (`url`, `publicUrl`, `assetsUrl`, `uploadsUrl`) anchored at `app.baseUrl`.
15
- - `upload-file` — handle multipart uploads: `request.file()`, `v.file()` validation, `UploadedFile.save()`.
16
- - `health-checks` — built-in `/health` + `/ready` endpoints, the `health` registry, and graceful request draining.
17
-
18
- ## Data layer
19
-
20
- - `use-repository` — subclass `RepositoryManager`: `source`/`filterBy`/`defaultOptions`, list/find/CRUD, cached/cursor variants, and the `filterBy`-aware aggregates (`sum`/`avg`/`min`/`max`/`groupBy`/`aggregate`).
21
- - `use-model-transformers` — schema-side helpers: `useHashedPassword()`, `useComputedSlug()`, and friends.
22
- - `define-resource` — map model fields to wire-shape via `defineResource()` / `Resource` subclasses (output-only); typed output with `ResourceOutput`, `Serialized<T, W>` and `ModelResourceRegistry`.
23
- - `write-seeder` — author a seed file with `seeder()` — `name`/`dependsOn`/`once`/`order`/`batchSize`, `run({ track, now, batchSize })`, `warlock seed --drop`.
24
-
25
- ## Files, media, mail
26
-
27
- - `store-file` — read/write/delete files via the `storage` singleton (local/S3/R2/DO Spaces), `StorageFile` handles, presigned URLs.
28
- - `process-image` — transform images with the `Image` class (resize, crop, rotate, format, watermark, …) on a deferred pipeline.
29
- - `send-mail` — send transactional email: the `Mail` fluent builder, `sendMail()`, React Email, test-mode capture.
30
-
31
- ## App, config, lifecycle
32
-
33
- - `configure-app` — the two config layers (`warlock.config.ts` vs `src/config/*.ts`), `.env` + `env()`.
34
- - `use-app-context` — read app-wide context via the `Application` static class and the `app` runtime accessor.
35
- - `add-connector` — extend the lifecycle with a `BaseConnector` subclass (`start`/`shutdown`/`watchedFiles`).
36
- - `wire-socket` — configure Socket.IO, reach the live server via `getSocketServer()` / `app.socket`.
37
- - `use-localization` — multi-locale translations: `groupedTranslations`, `t()` (always, never `request.t()`), locale resolution.
38
-
39
- ## Use-cases & services
40
-
41
- - `write-use-case` — author `useCase()` pipelines: guards, schema, before/after, retry, benchmark, broadcast, lifecycle.
42
- - `create-module` — scaffold a feature module under `src/app/<name>/` via `warlock generate.module` + follow-up generators.
43
- - `make-endpoint` — `warlock make endpoint <module>/<name>`: one spec-first endpoint (schema → service, resource, controller, route, locale key, OpenAPI response, HTTP test); `--dry-run` / `--json` on every generator.
44
-
45
- ## CLI & operations
46
-
47
- - `warlock-doctor` — `warlock doctor`: read-only diagnostics (routes/config/connectors/optional-peers/health/release-hygiene) with a pass/warn/fail report and non-zero exit on failure.
48
- - `warlock-inspect` — `warlock inspect [--json] [--section ...]`: the app's routes, models, resources, config keys, events, pages, jobs, schedules and package versions from the booted registries, as a versioned JSON report; `inspectApp()` from `@warlock.js/core/tooling`.
49
- - `warlock-check` — `warlock check` / `typecheck` / `explain`: one verify command (typecheck, lint, affected tests, conventions) with one JSON object per problem, stable `WL` error codes, and exit 1 for your code vs 2 for this machine.
50
- - `warlock-mcp` — `warlock mcp [--http] [--allow-writes]` and `warlock dev --mcp`: the app as an MCP server for coding agents — `inspect_*`, `db_schema`, offline `docs_search` over installed skills, `explain`, `check_run`, `test_run`, devtools `requests_recent`, and `generate_make` / `generate_add` that return a diff by default.
51
- - `warlock-trace` — `warlock trace <method> <url> [--json]`: send one request to the running dev server and print its devtools timeline (middleware, validation, queries with N+1 flags, logs, response, timings).
52
- - `warlock-agents-md` — `warlock agents-md [--write]`: the app-specific AGENTS.md section between `warlock:generated` markers, refreshed by `warlock dev`.
53
- - `warlock-board` — `warlock board init|add|status|send|watch`: a git-ignored task board with review states and append-only messages for an implementer and a reviewer agent.
54
- - `warlock-routes` — `warlock routes`: list the registered HTTP routes as a verb-colored table (method/path/name/action/middleware/source); filter by method/path/name or emit JSON. Read-only, no connectors.
55
- - `write-cli-command` — author a custom `warlock <cmd>` via the `command()` factory, or inspect built-in `warlock add` feature scaffolding such as the Web starter.
56
- - `generate-openapi` — `warlock generate.openapi`: an OpenAPI 3.1 document from the routes (validation, `responseSchema`, auth), plus the dev-only API docs page.
57
- - `run-app` — `warlock dev` / `warlock build` / `warlock start` operational commands.
58
- - `update-packages` — bump every `@warlock.js/*` dependency with `warlock update`.
59
-
60
- ## Testing
61
-
62
- - `test-http` — integration tests against a real HTTP server (`startHttpTestServer()`, `testGet` / `testPost`).
63
- - `test-service` — pure unit tests against services/repositories/models/use-cases via `setupTest({ connectors })`.
64
- - `store-secrets` — app-scoped credentials, lazy keychain/environment/encrypted file storage, memory backends and safe errors.
65
- - `test-fakes` — mail, queue, cache, storage, clock, ids and secrets fakes, on by default in tests, and their assertions; opting out.
66
- - `model-factories` — `defineFactory(Model, (seed) => attrs)`: deterministic `make()` / `create(n)` / states.
67
-
68
- ## Utilities
69
-
70
- - `encrypt-data` — reversible AES-256-GCM `encrypt`/`decrypt`, plus one-way `hmacHash` fingerprints.
71
- - `hash-password` — one-way bcrypt `hashPassword`/`verifyPassword` and the `useHashedPassword()` transformer.
72
- - `resolve-path` — path helpers anchored at `process.cwd()` (`rootPath`, `srcPath`, `appPath`, …).
73
- - `benchmark-code` — time a function with `measure(name, fn, options?)` and classify the latency.
74
- - `retry-operation` — wrap a flaky operation with `retry(fn, options)` (now from `@mongez/reinforcements`).
75
- - `lower-stage3-decorators` — the `lowerStage3Decorators()` Vite/Vitest plugin for native decorators.
76
- - `warlock-conventions` — framework-wide invariants: module layout, canonical imports, layered flow, file naming.