@codyswann/lisa 2.166.2 → 2.166.4

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 (61) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa-agy/plugin.json +1 -1
  5. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  8. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  9. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  14. package/plugins/lisa-expo-agy/plugin.json +1 -1
  15. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  17. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-harper-fabric/skills/harper-build-and-deploy/SKILL.md +70 -8
  20. package/plugins/lisa-harper-fabric/skills/harper-config-yaml/SKILL.md +172 -1
  21. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  22. package/plugins/lisa-harper-fabric-agy/skills/harper-build-and-deploy/SKILL.md +70 -8
  23. package/plugins/lisa-harper-fabric-agy/skills/harper-config-yaml/SKILL.md +172 -1
  24. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-harper-fabric-copilot/skills/harper-build-and-deploy/SKILL.md +70 -8
  26. package/plugins/lisa-harper-fabric-copilot/skills/harper-config-yaml/SKILL.md +172 -1
  27. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  28. package/plugins/lisa-harper-fabric-cursor/skills/harper-build-and-deploy/SKILL.md +70 -8
  29. package/plugins/lisa-harper-fabric-cursor/skills/harper-config-yaml/SKILL.md +172 -1
  30. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  33. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  38. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  43. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-rails-agy/plugin.json +1 -1
  48. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  53. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  57. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  58. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/src/harper-fabric/skills/harper-build-and-deploy/SKILL.md +70 -8
  61. package/plugins/src/harper-fabric/skills/harper-config-yaml/SKILL.md +172 -1
@@ -66,6 +66,175 @@ For real-time work, component `config.yaml` keeps `rest`, `graphqlSchema`, and
66
66
  MQTT topic paths. Broker ports and MQTT authentication live in the root
67
67
  `harper-config.yaml`, not the component file. See [[harper-realtime]].
68
68
 
69
+ ## `dataLoader`: seed data
70
+
71
+ Use `dataLoader` for versioned seed/reference records that should exist whenever
72
+ the component is deployed. Define table shape first with `graphqlSchema`, then
73
+ point `dataLoader.files` at one or more JSON/YAML files:
74
+
75
+ ```yaml
76
+ graphqlSchema:
77
+ files: 'schema.graphql'
78
+ dataLoader:
79
+ files:
80
+ - 'data/roles.yaml'
81
+ - 'data/reference/*.json'
82
+ ```
83
+
84
+ Each data file targets exactly one table and has `database`, `table`, and
85
+ `records` keys:
86
+
87
+ ```yaml
88
+ database: app
89
+ table: Role
90
+ records:
91
+ - id: admin
92
+ name: Administrator
93
+ permissions:
94
+ - users:read
95
+ - users:write
96
+ - id: viewer
97
+ name: Viewer
98
+ permissions:
99
+ - users:read
100
+ ```
101
+
102
+ Harper runs the loader on full system starts and component deployments. It is
103
+ safe to re-run when files are idempotent: new records are inserted, unchanged
104
+ records are skipped, and records are updated from the file only when the tracked
105
+ file content changed. User-created records and user edits made after an initial
106
+ load are preserved; changed data-loaded records are patched instead of blindly
107
+ replaced.
108
+
109
+ Choose `dataLoader` for small, source-controlled reference/configuration data
110
+ that should ship with the component. Use a REST/Operations API script or job for
111
+ large imports, environment-specific backfills, or one-off migrations where retry
112
+ scope and operator approval matter.
113
+
114
+ Verify locally:
115
+
116
+ ```bash
117
+ harper dev harper-app
118
+ curl -s http://localhost:9926/app/Role/admin
119
+ harper dev harper-app # restart/redeploy and confirm the seed did not duplicate
120
+ ```
121
+
122
+ ## `fastifyRoutes`: custom HTTP routes
123
+
124
+ Prefer `jsResource` plus `rest` for normal CRUD/action APIs. Use `fastifyRoutes`
125
+ only when the route shape does not fit the Resource model: webhooks, custom
126
+ serialization, unusual path matching, or a compatibility endpoint.
127
+
128
+ ```yaml
129
+ rest: true
130
+ graphqlSchema:
131
+ files: 'schema.graphql'
132
+ jsResource:
133
+ files: 'resources.js'
134
+ fastifyRoutes:
135
+ files: 'routes/*.js'
136
+ urlPath: 'hooks'
137
+ ```
138
+
139
+ Route modules default-export an async function that receives the Fastify server
140
+ and Harper helpers:
141
+
142
+ ```js
143
+ export default async (server, { hdbCore, logger }) => {
144
+ server.route({
145
+ method: 'POST',
146
+ url: '/payment/:provider',
147
+ preValidation: hdbCore.preValidation,
148
+ handler: async (request, reply) => {
149
+ logger.debug(`payment webhook ${request.params.provider}`);
150
+ request.body = {
151
+ operation: 'insert',
152
+ schema: 'app',
153
+ table: 'WebhookEvent',
154
+ records: [
155
+ {
156
+ id: request.headers['x-event-id'],
157
+ provider: request.params.provider,
158
+ payload: request.body,
159
+ },
160
+ ],
161
+ };
162
+ const result = await hdbCore.request(request);
163
+ return { ok: true, result };
164
+ },
165
+ });
166
+ };
167
+ ```
168
+
169
+ Use Fastify's `request.params`, `request.query`, `request.body`, and `request.headers`
170
+ for route inputs. Keep auth explicit: `hdbCore.request` should be paired with
171
+ `hdbCore.preValidation` so Harper authenticates the request. Avoid
172
+ `requestWithoutAuthentication` unless the route has its own signature/JWT check
173
+ and all user-provided values are bound or escaped; never build SQL strings by
174
+ interpolating params/body values.
175
+
176
+ Verify locally:
177
+
178
+ ```bash
179
+ harper dev harper-app
180
+ curl -i -X POST http://localhost:9926/app/hooks/payment/stripe \
181
+ -H 'Authorization: Basic ...' \
182
+ -H 'Content-Type: application/json' \
183
+ -H 'x-event-id: evt_123' \
184
+ --data '{"status":"paid"}'
185
+ ```
186
+
187
+ ## `static`: serve web assets and SPAs
188
+
189
+ Use `static` to serve generated browser output or other immutable assets from
190
+ the component. In Lisa Harper Fabric projects, `harper-app/web/**` is generated
191
+ by the project build; edit the source UI under `src/`, not the deployed files.
192
+
193
+ ```yaml
194
+ static:
195
+ files: 'web/**'
196
+ urlPath: '.'
197
+ index: true
198
+ ```
199
+
200
+ `files` selects what is served. `urlPath` mounts those files under a URL prefix:
201
+ `urlPath: 'app'` makes `web/index.html` available at `/app/index.html`; the
202
+ default application path still includes the Harper project/component prefix. Use
203
+ `index: true` to serve `index.html` for directory requests, and `extensions:
204
+ ['html']` when clean URLs should resolve to `.html` files.
205
+
206
+ For client-side-routed SPAs, return the app shell for unmatched asset paths:
207
+
208
+ ```yaml
209
+ static:
210
+ files: 'web/**'
211
+ urlPath: '.'
212
+ index: true
213
+ fallthrough: false
214
+ notFound:
215
+ file: 'web/index.html'
216
+ statusCode: 200
217
+ ```
218
+
219
+ That fallback is for browser routes such as `/reports/weekly`; it should not hide
220
+ missing API endpoints or broken asset names. Keep API routes under a clear
221
+ prefix, and check that hashed JS/CSS assets still return their actual files.
222
+
223
+ Harper's documented `static` config controls path matching and not-found
224
+ behavior, not custom cache policy. Treat MIME type and cache headers as runtime
225
+ behavior to verify with `curl -I`; if the app needs precise cache headers,
226
+ front it with an edge/proxy policy or a custom route designed for that asset
227
+ surface.
228
+
229
+ Verify locally:
230
+
231
+ ```bash
232
+ harper dev harper-app
233
+ curl -I http://localhost:9926/app/
234
+ curl -I http://localhost:9926/app/assets/index.js
235
+ curl -I http://localhost:9926/app/client-side-route
236
+ ```
237
+
69
238
  ## External components and custom plugins
70
239
 
71
240
  A component you depend on from npm needs a `package:` directive matching a
@@ -109,4 +278,6 @@ dropped an extension often fails only at runtime, not at build time.
109
278
  ## Sources
110
279
 
111
280
  - [Components overview](https://docs.harperdb.io/reference/v5/components/overview)
112
- - [Built-in extensions](https://docs.harperdb.io/docs/reference/components/built-in-extensions)
281
+ - [Data Loader](https://docs.harperdb.io/reference/v5/database/data-loader)
282
+ - [Fastify Routes](https://docs.harperdb.io/reference/v5/fastify-routes/overview)
283
+ - [Static Files](https://docs.harperdb.io/reference/v5/static-files/overview)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.166.2",
3
+ "version": "2.166.4",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -27,14 +27,42 @@ The CLI binary is `harper` (v5; older installs use `harperdb`). Key commands:
27
27
  In this project, dev typically runs against the component dir, e.g.
28
28
  `harper dev harper-app` (use the project's documented run command if it wraps this).
29
29
 
30
- ## The build step (TypeScript generated artifacts)
30
+ ## The build step (TypeScript -> generated artifacts)
31
31
 
32
32
  Harper loads JavaScript (`resources.js`) and serves static files (`web/**`). In this
33
- project those are **generated**, not authored:
34
-
35
- - **TypeScript under `src/` is source.** `bun run build` compiles it into
36
- `harper-app/resources.js` and `harper-app/web/**`.
37
- - **Never edit `resources.js` or `web/**` directly** change the TypeScript and
33
+ project those are **generated**, not authored.
34
+
35
+ What the build actually does:
36
+
37
+ 1. Compiles the TypeScript source under `src/` into deployable JavaScript.
38
+ 2. Emits `harper-app/resources.js`, the aggregate resource module loaded by the
39
+ `jsResource` extension.
40
+ 3. Emits per-resource modules such as `harper-app/resource-*.js` when the project
41
+ build splits resources for Harper's runtime loader.
42
+ 4. Copies browser/static output into `harper-app/web/**` for the `static`
43
+ extension to serve.
44
+ 5. Mirrors shared library output into `harper-app/lib/**` and rewrites imports
45
+ such as `../lib/foo.js` to `./lib/foo.js`. Fabric packages the component root
46
+ as a flat deploy unit, and Node resolves real paths at runtime, so imports must
47
+ point at files that exist inside the packaged `harper-app/` root.
48
+ 6. Adds cache-busting `?v=` query parameters to browser-module imports when the
49
+ project build owns web asset versioning.
50
+
51
+ Generated Harper deploy artifacts usually include:
52
+
53
+ - `harper-app/resources.js`
54
+ - `harper-app/resource-*.js`
55
+ - `harper-app/web/**`
56
+ - `harper-app/lib/**`
57
+
58
+ Every lint, format, dead-code, search, or generated-artifact guard must ignore
59
+ those generated paths unless it is explicitly validating the build output itself.
60
+ When a new generated path appears, add it to every relevant ignore surface in the
61
+ same change; partial ignores fail later gates in non-obvious ways.
62
+
63
+ - **TypeScript under `src/` is source.** `bun run build` produces the deployable
64
+ Harper assets from it.
65
+ - **Never edit generated Harper assets directly** — change the TypeScript and
38
66
  rebuild. See [[harper-resources]] and [[harper-component-model]].
39
67
  - **Build before symlinking, packaging, or deploying `harper-app/`.** Deploying
40
68
  stale artifacts ships code that does not match `src/`.
@@ -86,11 +114,45 @@ harper deploy_component \
86
114
 
87
115
  - Omitting `package` deploys the current directory.
88
116
  - `restart=true` restarts threads after deploy so new code loads.
89
- - `replicated=true` replicates the deploy across all nodes in a cluster — include it
90
- when targeting Fabric/a cluster.
117
+ - `replicated=true` asks Harper/Fabric to apply the component deploy across the
118
+ cluster rather than only the node receiving the deploy request. Include it when
119
+ targeting Fabric or any clustered deployment.
91
120
  - Credentials can come from `CLI_TARGET_USERNAME` / `CLI_TARGET_PASSWORD` instead of
92
121
  inline flags — prefer that so secrets never land in shell history or tracked files.
93
122
 
123
+ ## Replication and topology
124
+
125
+ Fabric is a distributed runtime: a project can run on one or more Harper nodes,
126
+ often grouped by region or environment. Your application code is packaged as a
127
+ component, and the data layer is replicated through Harper's database and
128
+ clustering model.
129
+
130
+ Keep these semantics separate:
131
+
132
+ - **Component code replication** is controlled by deploy behavior. With
133
+ `replicated=true`, the deployed component package should reach the cluster nodes
134
+ that serve the application. Without it, you may update only the target node and
135
+ leave other nodes running older code.
136
+ - **Data replication** is runtime/database behavior. Deploying code does not by
137
+ itself prove that existing rows, schema changes, caches, or realtime state are
138
+ consistent across regions or nodes.
139
+ - **Thread restart** is local process behavior. `restart=true` reloads code after
140
+ the package lands; it is not a substitute for checking every node or region that
141
+ receives traffic.
142
+
143
+ After a replicated deploy, verify from the topology the app actually uses:
144
+
145
+ 1. Confirm the deploy command or workflow used `replicated=true` for Fabric/cluster
146
+ targets.
147
+ 2. Read `harper status` or the project's Fabric status command to see the expected
148
+ nodes/regions.
149
+ 3. Hit the public smoke endpoint through the production route, then hit a direct
150
+ node or region endpoint when the project exposes one.
151
+ 4. For schema or data changes, verify a write/read path that proves the expected
152
+ data is visible where traffic can land.
153
+ 5. If one node serves old assets or resources, treat the deploy as incomplete even
154
+ when the initial target node passed smoke.
155
+
94
156
  ## Secrets
95
157
 
96
158
  Keep runtime secrets out of tracked files. Use environment variables, the
@@ -66,6 +66,175 @@ For real-time work, component `config.yaml` keeps `rest`, `graphqlSchema`, and
66
66
  MQTT topic paths. Broker ports and MQTT authentication live in the root
67
67
  `harper-config.yaml`, not the component file. See [[harper-realtime]].
68
68
 
69
+ ## `dataLoader`: seed data
70
+
71
+ Use `dataLoader` for versioned seed/reference records that should exist whenever
72
+ the component is deployed. Define table shape first with `graphqlSchema`, then
73
+ point `dataLoader.files` at one or more JSON/YAML files:
74
+
75
+ ```yaml
76
+ graphqlSchema:
77
+ files: 'schema.graphql'
78
+ dataLoader:
79
+ files:
80
+ - 'data/roles.yaml'
81
+ - 'data/reference/*.json'
82
+ ```
83
+
84
+ Each data file targets exactly one table and has `database`, `table`, and
85
+ `records` keys:
86
+
87
+ ```yaml
88
+ database: app
89
+ table: Role
90
+ records:
91
+ - id: admin
92
+ name: Administrator
93
+ permissions:
94
+ - users:read
95
+ - users:write
96
+ - id: viewer
97
+ name: Viewer
98
+ permissions:
99
+ - users:read
100
+ ```
101
+
102
+ Harper runs the loader on full system starts and component deployments. It is
103
+ safe to re-run when files are idempotent: new records are inserted, unchanged
104
+ records are skipped, and records are updated from the file only when the tracked
105
+ file content changed. User-created records and user edits made after an initial
106
+ load are preserved; changed data-loaded records are patched instead of blindly
107
+ replaced.
108
+
109
+ Choose `dataLoader` for small, source-controlled reference/configuration data
110
+ that should ship with the component. Use a REST/Operations API script or job for
111
+ large imports, environment-specific backfills, or one-off migrations where retry
112
+ scope and operator approval matter.
113
+
114
+ Verify locally:
115
+
116
+ ```bash
117
+ harper dev harper-app
118
+ curl -s http://localhost:9926/app/Role/admin
119
+ harper dev harper-app # restart/redeploy and confirm the seed did not duplicate
120
+ ```
121
+
122
+ ## `fastifyRoutes`: custom HTTP routes
123
+
124
+ Prefer `jsResource` plus `rest` for normal CRUD/action APIs. Use `fastifyRoutes`
125
+ only when the route shape does not fit the Resource model: webhooks, custom
126
+ serialization, unusual path matching, or a compatibility endpoint.
127
+
128
+ ```yaml
129
+ rest: true
130
+ graphqlSchema:
131
+ files: 'schema.graphql'
132
+ jsResource:
133
+ files: 'resources.js'
134
+ fastifyRoutes:
135
+ files: 'routes/*.js'
136
+ urlPath: 'hooks'
137
+ ```
138
+
139
+ Route modules default-export an async function that receives the Fastify server
140
+ and Harper helpers:
141
+
142
+ ```js
143
+ export default async (server, { hdbCore, logger }) => {
144
+ server.route({
145
+ method: 'POST',
146
+ url: '/payment/:provider',
147
+ preValidation: hdbCore.preValidation,
148
+ handler: async (request, reply) => {
149
+ logger.debug(`payment webhook ${request.params.provider}`);
150
+ request.body = {
151
+ operation: 'insert',
152
+ schema: 'app',
153
+ table: 'WebhookEvent',
154
+ records: [
155
+ {
156
+ id: request.headers['x-event-id'],
157
+ provider: request.params.provider,
158
+ payload: request.body,
159
+ },
160
+ ],
161
+ };
162
+ const result = await hdbCore.request(request);
163
+ return { ok: true, result };
164
+ },
165
+ });
166
+ };
167
+ ```
168
+
169
+ Use Fastify's `request.params`, `request.query`, `request.body`, and `request.headers`
170
+ for route inputs. Keep auth explicit: `hdbCore.request` should be paired with
171
+ `hdbCore.preValidation` so Harper authenticates the request. Avoid
172
+ `requestWithoutAuthentication` unless the route has its own signature/JWT check
173
+ and all user-provided values are bound or escaped; never build SQL strings by
174
+ interpolating params/body values.
175
+
176
+ Verify locally:
177
+
178
+ ```bash
179
+ harper dev harper-app
180
+ curl -i -X POST http://localhost:9926/app/hooks/payment/stripe \
181
+ -H 'Authorization: Basic ...' \
182
+ -H 'Content-Type: application/json' \
183
+ -H 'x-event-id: evt_123' \
184
+ --data '{"status":"paid"}'
185
+ ```
186
+
187
+ ## `static`: serve web assets and SPAs
188
+
189
+ Use `static` to serve generated browser output or other immutable assets from
190
+ the component. In Lisa Harper Fabric projects, `harper-app/web/**` is generated
191
+ by the project build; edit the source UI under `src/`, not the deployed files.
192
+
193
+ ```yaml
194
+ static:
195
+ files: 'web/**'
196
+ urlPath: '.'
197
+ index: true
198
+ ```
199
+
200
+ `files` selects what is served. `urlPath` mounts those files under a URL prefix:
201
+ `urlPath: 'app'` makes `web/index.html` available at `/app/index.html`; the
202
+ default application path still includes the Harper project/component prefix. Use
203
+ `index: true` to serve `index.html` for directory requests, and `extensions:
204
+ ['html']` when clean URLs should resolve to `.html` files.
205
+
206
+ For client-side-routed SPAs, return the app shell for unmatched asset paths:
207
+
208
+ ```yaml
209
+ static:
210
+ files: 'web/**'
211
+ urlPath: '.'
212
+ index: true
213
+ fallthrough: false
214
+ notFound:
215
+ file: 'web/index.html'
216
+ statusCode: 200
217
+ ```
218
+
219
+ That fallback is for browser routes such as `/reports/weekly`; it should not hide
220
+ missing API endpoints or broken asset names. Keep API routes under a clear
221
+ prefix, and check that hashed JS/CSS assets still return their actual files.
222
+
223
+ Harper's documented `static` config controls path matching and not-found
224
+ behavior, not custom cache policy. Treat MIME type and cache headers as runtime
225
+ behavior to verify with `curl -I`; if the app needs precise cache headers,
226
+ front it with an edge/proxy policy or a custom route designed for that asset
227
+ surface.
228
+
229
+ Verify locally:
230
+
231
+ ```bash
232
+ harper dev harper-app
233
+ curl -I http://localhost:9926/app/
234
+ curl -I http://localhost:9926/app/assets/index.js
235
+ curl -I http://localhost:9926/app/client-side-route
236
+ ```
237
+
69
238
  ## External components and custom plugins
70
239
 
71
240
  A component you depend on from npm needs a `package:` directive matching a
@@ -109,4 +278,6 @@ dropped an extension often fails only at runtime, not at build time.
109
278
  ## Sources
110
279
 
111
280
  - [Components overview](https://docs.harperdb.io/reference/v5/components/overview)
112
- - [Built-in extensions](https://docs.harperdb.io/docs/reference/components/built-in-extensions)
281
+ - [Data Loader](https://docs.harperdb.io/reference/v5/database/data-loader)
282
+ - [Fastify Routes](https://docs.harperdb.io/reference/v5/fastify-routes/overview)
283
+ - [Static Files](https://docs.harperdb.io/reference/v5/static-files/overview)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.166.2",
3
+ "version": "2.166.4",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -27,14 +27,42 @@ The CLI binary is `harper` (v5; older installs use `harperdb`). Key commands:
27
27
  In this project, dev typically runs against the component dir, e.g.
28
28
  `harper dev harper-app` (use the project's documented run command if it wraps this).
29
29
 
30
- ## The build step (TypeScript generated artifacts)
30
+ ## The build step (TypeScript -> generated artifacts)
31
31
 
32
32
  Harper loads JavaScript (`resources.js`) and serves static files (`web/**`). In this
33
- project those are **generated**, not authored:
34
-
35
- - **TypeScript under `src/` is source.** `bun run build` compiles it into
36
- `harper-app/resources.js` and `harper-app/web/**`.
37
- - **Never edit `resources.js` or `web/**` directly** change the TypeScript and
33
+ project those are **generated**, not authored.
34
+
35
+ What the build actually does:
36
+
37
+ 1. Compiles the TypeScript source under `src/` into deployable JavaScript.
38
+ 2. Emits `harper-app/resources.js`, the aggregate resource module loaded by the
39
+ `jsResource` extension.
40
+ 3. Emits per-resource modules such as `harper-app/resource-*.js` when the project
41
+ build splits resources for Harper's runtime loader.
42
+ 4. Copies browser/static output into `harper-app/web/**` for the `static`
43
+ extension to serve.
44
+ 5. Mirrors shared library output into `harper-app/lib/**` and rewrites imports
45
+ such as `../lib/foo.js` to `./lib/foo.js`. Fabric packages the component root
46
+ as a flat deploy unit, and Node resolves real paths at runtime, so imports must
47
+ point at files that exist inside the packaged `harper-app/` root.
48
+ 6. Adds cache-busting `?v=` query parameters to browser-module imports when the
49
+ project build owns web asset versioning.
50
+
51
+ Generated Harper deploy artifacts usually include:
52
+
53
+ - `harper-app/resources.js`
54
+ - `harper-app/resource-*.js`
55
+ - `harper-app/web/**`
56
+ - `harper-app/lib/**`
57
+
58
+ Every lint, format, dead-code, search, or generated-artifact guard must ignore
59
+ those generated paths unless it is explicitly validating the build output itself.
60
+ When a new generated path appears, add it to every relevant ignore surface in the
61
+ same change; partial ignores fail later gates in non-obvious ways.
62
+
63
+ - **TypeScript under `src/` is source.** `bun run build` produces the deployable
64
+ Harper assets from it.
65
+ - **Never edit generated Harper assets directly** — change the TypeScript and
38
66
  rebuild. See [[harper-resources]] and [[harper-component-model]].
39
67
  - **Build before symlinking, packaging, or deploying `harper-app/`.** Deploying
40
68
  stale artifacts ships code that does not match `src/`.
@@ -86,11 +114,45 @@ harper deploy_component \
86
114
 
87
115
  - Omitting `package` deploys the current directory.
88
116
  - `restart=true` restarts threads after deploy so new code loads.
89
- - `replicated=true` replicates the deploy across all nodes in a cluster — include it
90
- when targeting Fabric/a cluster.
117
+ - `replicated=true` asks Harper/Fabric to apply the component deploy across the
118
+ cluster rather than only the node receiving the deploy request. Include it when
119
+ targeting Fabric or any clustered deployment.
91
120
  - Credentials can come from `CLI_TARGET_USERNAME` / `CLI_TARGET_PASSWORD` instead of
92
121
  inline flags — prefer that so secrets never land in shell history or tracked files.
93
122
 
123
+ ## Replication and topology
124
+
125
+ Fabric is a distributed runtime: a project can run on one or more Harper nodes,
126
+ often grouped by region or environment. Your application code is packaged as a
127
+ component, and the data layer is replicated through Harper's database and
128
+ clustering model.
129
+
130
+ Keep these semantics separate:
131
+
132
+ - **Component code replication** is controlled by deploy behavior. With
133
+ `replicated=true`, the deployed component package should reach the cluster nodes
134
+ that serve the application. Without it, you may update only the target node and
135
+ leave other nodes running older code.
136
+ - **Data replication** is runtime/database behavior. Deploying code does not by
137
+ itself prove that existing rows, schema changes, caches, or realtime state are
138
+ consistent across regions or nodes.
139
+ - **Thread restart** is local process behavior. `restart=true` reloads code after
140
+ the package lands; it is not a substitute for checking every node or region that
141
+ receives traffic.
142
+
143
+ After a replicated deploy, verify from the topology the app actually uses:
144
+
145
+ 1. Confirm the deploy command or workflow used `replicated=true` for Fabric/cluster
146
+ targets.
147
+ 2. Read `harper status` or the project's Fabric status command to see the expected
148
+ nodes/regions.
149
+ 3. Hit the public smoke endpoint through the production route, then hit a direct
150
+ node or region endpoint when the project exposes one.
151
+ 4. For schema or data changes, verify a write/read path that proves the expected
152
+ data is visible where traffic can land.
153
+ 5. If one node serves old assets or resources, treat the deploy as incomplete even
154
+ when the initial target node passed smoke.
155
+
94
156
  ## Secrets
95
157
 
96
158
  Keep runtime secrets out of tracked files. Use environment variables, the