@harperfast/template-react-ts-studio 1.11.3 → 1.11.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 (48) hide show
  1. package/.agents/skills/harper-best-practices/AGENTS.md +567 -490
  2. package/.agents/skills/harper-best-practices/rules/automatic-apis.md +46 -78
  3. package/.agents/skills/harper-best-practices/rules/defining-relationships.md +41 -63
  4. package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +59 -45
  5. package/.agents/skills/harper-best-practices/rules/load-env.md +24 -23
  6. package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +62 -78
  7. package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +92 -65
  8. package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +53 -55
  9. package/.agents/skills/harper-best-practices/rules/v5-upgrade.md +98 -62
  10. package/.agents/skills/harper-best-practices/rules/vector-indexing.md +113 -42
  11. package/.agents/skills/harper-mcp/AGENTS.md +501 -0
  12. package/.agents/skills/harper-mcp/SKILL.md +91 -0
  13. package/.agents/skills/harper-mcp/rules/automatic-verb-tools.md +50 -0
  14. package/.agents/skills/harper-mcp/rules/connecting-clients.md +59 -0
  15. package/.agents/skills/harper-mcp/rules/custom-mcp-prompts.md +52 -0
  16. package/.agents/skills/harper-mcp/rules/custom-mcp-resources.md +64 -0
  17. package/.agents/skills/harper-mcp/rules/custom-mcp-tools.md +72 -0
  18. package/.agents/skills/harper-mcp/rules/durable-quotas.md +73 -0
  19. package/.agents/skills/harper-mcp/rules/enabling-mcp.md +63 -0
  20. package/.agents/skills/harper-mcp/rules/rate-limiting.md +62 -0
  21. package/.agents/skills/harper-mcp/rules/resources-surface.md +44 -0
  22. package/.agents/skills/harper-mcp/rules/security-posture.md +36 -0
  23. package/.agents/skills/harper-mcp/rules.manifest.yaml +203 -0
  24. package/agent/skills/harper-best-practices/AGENTS.md +567 -490
  25. package/agent/skills/harper-best-practices/rules/automatic-apis.md +46 -78
  26. package/agent/skills/harper-best-practices/rules/defining-relationships.md +41 -63
  27. package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +59 -45
  28. package/agent/skills/harper-best-practices/rules/load-env.md +24 -23
  29. package/agent/skills/harper-best-practices/rules/programmatic-table-requests.md +62 -78
  30. package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +92 -65
  31. package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +53 -55
  32. package/agent/skills/harper-best-practices/rules/v5-upgrade.md +98 -62
  33. package/agent/skills/harper-best-practices/rules/vector-indexing.md +113 -42
  34. package/agent/skills/harper-mcp/AGENTS.md +501 -0
  35. package/agent/skills/harper-mcp/SKILL.md +83 -0
  36. package/agent/skills/harper-mcp/rules/automatic-verb-tools.md +50 -0
  37. package/agent/skills/harper-mcp/rules/connecting-clients.md +59 -0
  38. package/agent/skills/harper-mcp/rules/custom-mcp-prompts.md +52 -0
  39. package/agent/skills/harper-mcp/rules/custom-mcp-resources.md +64 -0
  40. package/agent/skills/harper-mcp/rules/custom-mcp-tools.md +72 -0
  41. package/agent/skills/harper-mcp/rules/durable-quotas.md +73 -0
  42. package/agent/skills/harper-mcp/rules/enabling-mcp.md +63 -0
  43. package/agent/skills/harper-mcp/rules/rate-limiting.md +62 -0
  44. package/agent/skills/harper-mcp/rules/resources-surface.md +44 -0
  45. package/agent/skills/harper-mcp/rules/security-posture.md +36 -0
  46. package/agent/skills/harper-mcp/rules.manifest.yaml +203 -0
  47. package/package.json +1 -1
  48. package/skills-lock.json +7 -1
@@ -9,8 +9,8 @@ metadata:
9
9
  - reference/v5/database/schema.md#Overview
10
10
  - reference/v5/database/schema.md#Type Directives
11
11
  - reference/v5/database/schema.md#Field Directives
12
- sourceCommit: 4fe4c9c95e0974eaa77032f6f10e36fbd8ec64ac
13
- inputHash: 15b9c72decc1f05d
12
+ sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
13
+ inputHash: ce22f3fefb660c6e
14
14
  ---
15
15
 
16
16
  # Schema Design and GraphQL Tooling
@@ -19,13 +19,11 @@ Instructions for the agent to follow when designing Harper schemas, applying cor
19
19
 
20
20
  ## When to Use
21
21
 
22
- Apply this rule when creating or modifying Harper schema files, configuring `graphqlSchema` in `config.yaml`, or deciding which directives to apply to tables and fields. Use it any time a component needs tables, indexes, primary keys, or exported endpoints defined.
22
+ Apply this rule when creating or modifying Harper schema files (`.graphql`), configuring `graphqlSchema` in `config.yaml`, or deciding which directives to apply to types and fields. Use it any time you need to define tables, primary keys, indexes, or exported endpoints.
23
23
 
24
24
  ## How It Works
25
25
 
26
- 1. **Create a schema file** using standard GraphQL type definitions with Harper-specific directives. Name it (e.g., `schema.graphql`) and place it in your component directory.
27
-
28
- 2. **Register the schema** in the component's `config.yaml` using the `graphqlSchema` plugin:
26
+ 1. **Declare the schema file** in the component's `config.yaml` using the `graphqlSchema` plugin:
29
27
 
30
28
  ```yaml
31
29
  graphqlSchema:
@@ -34,7 +32,7 @@ Apply this rule when creating or modifying Harper schema files, configuring `gra
34
32
 
35
33
  Both plugins and applications can specify schemas.
36
34
 
37
- 3. **Mark types as tables** with `@table`. The type name becomes the table name by default:
35
+ 2. **Mark types as tables** with `@table`. The type name becomes the table name by default:
38
36
 
39
37
  ```graphql
40
38
  type Dog @table {
@@ -45,13 +43,13 @@ Apply this rule when creating or modifying Harper schema files, configuring `gra
45
43
  }
46
44
  ```
47
45
 
48
- 4. **Designate a primary key** with `@primaryKey` on exactly one field per type. Primary keys must be unique; duplicate-key inserts are rejected. If no primary key is provided on insert, Harper auto-generates one:
46
+ 3. **Set a primary key** on every table using `@primaryKey`. Primary keys must be unique; duplicate-key inserts are rejected. If no primary key is provided on insert, Harper auto-generates one based on the field type:
49
47
  - `String` or `ID` → UUID string
50
48
  - `Int`, `Long`, or `Any` → auto-incrementing integer
51
49
 
52
50
  Use `Long` or `Any` for auto-generated numeric keys; `Int` is 32-bit and may be insufficient for large tables.
53
51
 
54
- 5. **Add secondary indexes** with `@indexed` on any field that will be used for filtering in REST queries, SQL, or NoSQL operations:
52
+ 4. **Index fields for querying** with `@indexed`. Required for filtering by an attribute in REST queries, SQL, or NoSQL operations:
55
53
 
56
54
  ```graphql
57
55
  type Breed @table {
@@ -62,7 +60,7 @@ Apply this rule when creating or modifying Harper schema files, configuring `gra
62
60
 
63
61
  If the field value is an array, each element is individually indexed. Null values are indexed by default.
64
62
 
65
- 6. **Expose a table as an external endpoint** with `@export`. The optional `name` parameter sets the URL path segment:
63
+ 5. **Expose a table as an external endpoint** with `@export`. Available via REST, MQTT, and other interfaces. The optional `name` parameter sets the URL path segment:
66
64
 
67
65
  ```graphql
68
66
  type MyTable @table @export(name: "my-table") {
@@ -70,9 +68,9 @@ Apply this rule when creating or modifying Harper schema files, configuring `gra
70
68
  }
71
69
  ```
72
70
 
73
- Without `name`, the type name is used as the path segment.
71
+ Without `name`, the type name is used.
74
72
 
75
- 7. **Configure `@table` arguments** as needed for database placement, expiration, eviction, and replication:
73
+ 6. **Configure `@table` arguments** as needed. All arguments are optional:
76
74
 
77
75
  | Argument | Type | Default | Description |
78
76
  | -------------- | --------- | ----------------------------- | ------------------------------------------------------------- |
@@ -83,13 +81,15 @@ Apply this rule when creating or modifying Harper schema files, configuring `gra
83
81
  | `scanInterval` | `Int` | `(expiration + eviction) / 4` | Seconds between eviction scans |
84
82
  | `replicate` | `Boolean` | `true` | Enable replication of this table |
85
83
 
86
- 8. **Apply additional field directives** where needed:
87
- - `@createdTime` — auto-assigns Unix epoch milliseconds on record creation
88
- - `@updatedTime` — auto-assigns Unix epoch milliseconds on each update
89
- - `@embed(source: "fieldName", model: "modelName")` — computes an embedding vector on write; attribute type must be `[Float]`
90
- - `@hidden` — suppresses the field from MCP tool descriptors and OpenAPI documents (not an access-control mechanism)
84
+ 7. **Apply additional field directives** where needed:
85
+ - `@createdTime` — auto-assigns creation timestamp (Unix epoch ms)
86
+ - `@updatedTime` — auto-assigns update timestamp (Unix epoch ms)
87
+ - `@expiresAt` — marks a field as the record's absolute expiration time (Unix epoch ms)
88
+ - `@embed(source:, model:)` — computes an embedding vector when the source field is written; field type must be `[Float]`
89
+ - `@hidden` — suppresses the field from MCP tool descriptors and OpenAPI document (not an access-control mechanism)
90
+
91
+ 8. **Use `@sealed`** on a type to prevent records from including properties beyond those declared in the schema:
91
92
 
92
- 9. **Restrict extra properties** with `@sealed` if records must not include properties beyond those declared:
93
93
  ```graphql
94
94
  type StrictRecord @table @sealed {
95
95
  id: Long @primaryKey
@@ -97,9 +97,11 @@ Apply this rule when creating or modifying Harper schema files, configuring `gra
97
97
  }
98
98
  ```
99
99
 
100
+ 9. **Use unique database names** in plugins or applications to avoid table naming collisions, since all tables default to the `data` database.
101
+
100
102
  ## Examples
101
103
 
102
- **Minimal two-table schema:**
104
+ **Minimal schema with two tables:**
103
105
 
104
106
  ```graphql
105
107
  type Dog @table {
@@ -115,7 +117,7 @@ type Breed @table {
115
117
  }
116
118
  ```
117
119
 
118
- **Table with expiration, eviction, and custom scan interval:**
120
+ **Table with expiration, eviction, and scan tuning:**
119
121
 
120
122
  ```graphql
121
123
  # Expire after 5 minutes, evict after 1 hour, scan every 10 minutes
@@ -125,60 +127,56 @@ type WeatherCache @table(expiration: 300, eviction: 3300, scanInterval: 600) {
125
127
  }
126
128
  ```
127
129
 
128
- **Exported table with timestamps and a hidden field:**
130
+ **Table with multiple `@table` arguments combined:**
129
131
 
130
132
  ```graphql
131
- type Customer @table @export(name: "customers") {
133
+ type Event @table(database: "analytics", expiration: 86400) {
132
134
  id: Long @primaryKey
133
135
  name: String @indexed
134
- createdAt: Long @createdTime
135
- updatedAt: Long @updatedTime
136
-
137
- """
138
- Internal — do not surface to external consumers.
139
- """
140
- creditScore: Int @hidden
141
136
  }
142
137
  ```
143
138
 
144
- **Multiple `@table` argument combinations:**
139
+ **Exported table with overridden table name:**
145
140
 
146
141
  ```graphql
147
- # Override table name
148
- type Product @table(table: "products") {
142
+ type Product @table(table: "products") @export(name: "products") {
149
143
  id: Long @primaryKey
144
+ category: String @indexed
145
+ price: Float @indexed
150
146
  }
147
+ ```
151
148
 
152
- # Place in a specific database
153
- type Order @table(database: "commerce") {
154
- id: Long @primaryKey
155
- }
149
+ **Table with timestamps and per-record expiration:**
156
150
 
157
- # Auto-expire records after 1 hour
158
- type Session @table(expiration: 3600) {
159
- id: Long @primaryKey
160
- userId: String
151
+ ```graphql
152
+ type Session @table {
153
+ id: ID @primaryKey
154
+ token: String
155
+ createdAt: Long @createdTime
156
+ updatedAt: Long @updatedTime
157
+ expiresAt: Long @expiresAt
161
158
  }
159
+ ```
162
160
 
163
- # Disable replication
164
- type LocalRecord @table(replicate: false) {
165
- id: Long @primaryKey
166
- value: String
167
- }
161
+ **Table with a hidden internal field:**
168
162
 
169
- # Combine multiple arguments
170
- type Event @table(database: "analytics", expiration: 86400) {
163
+ ```graphql
164
+ type Customer @table {
171
165
  id: Long @primaryKey
172
- name: String @indexed
166
+ name: String
167
+
168
+ """
169
+ Internal — do not surface to external consumers.
170
+ """
171
+ creditScore: Int @hidden
173
172
  }
174
173
  ```
175
174
 
176
175
  ## Notes
177
176
 
178
- - All tables default to the `"data"` database. When designing plugins or applications, use unique database names to avoid table naming collisions.
179
- - Schemas are flexible by default — records may include properties beyond those declared. Use `@sealed` to prevent this.
180
- - `expiration` marks a record stale; `eviction` controls how long after expiration the record is physically removed. Eviction does not remove records from secondary indexes — Harper fetches the full record on demand if an evicted record matches a query.
181
- - `scanInterval` is clock-aligned to the server's local timezone, not startup-aligned. The eviction schedule is deterministic across restarts.
182
- - If replication is disabled on a table and later re-enabled, writes made during the disabled period are not replicated retroactively.
183
- - `@hidden` (on types or fields) is a metadata-visibility directive only. Use `attribute_permissions` on roles to enforce data access control.
184
- - Disabling replication (`replicate: false`) and re-enabling it later will not catch up on writes made while replication was disabled.
177
+ - `@table`, `@export`, `@sealed`, and `@hidden` are type-level directives; `@primaryKey`, `@indexed`, `@embed`, `@createdTime`, `@updatedTime`, `@expiresAt`, and `@hidden` are field-level directives.
178
+ - `eviction` removes non-indexed record data but does **not** remove a record from its secondary indexes. Indexes remain functional for evicted records; Harper fetches the full record on demand when a query matches an evicted entry.
179
+ - `scanInterval` is clock-aligned to the server's local timezone, not startup-aligned. The server's startup time does not affect when eviction runs.
180
+ - Replication is enabled by default. If you disable replication on a table and re-enable it later, it will not catch up on writes made while replication was disabled.
181
+ - `@hidden` is a metadata-visibility directive only. Use `attribute_permissions` on roles to enforce data access control.
182
+ - A full-record `put` that omits an `@expiresAt` field clears it; a `patch` of other fields preserves it.
@@ -7,101 +7,137 @@ metadata:
7
7
  mode: generate
8
8
  sources:
9
9
  - release-notes/v5-lincoln/v5-migration.md
10
- sourceCommit: de2aaf1c759a7ff5b93e862ba704153e2a392fcb
11
- inputHash: 80314689f3a7f42e
10
+ sourceCommit: 3749d0c54be457a2a65d9a63c738a5dc88989ecd
11
+ inputHash: 5ee6407370219136
12
12
  ---
13
13
 
14
- # Upgrading a Harper Application to v5
14
+ # v5 Upgrade: Breaking Changes and Migration Guide
15
15
 
16
- Instructions for the agent to follow when migrating an existing Harper application to version 5, addressing the breaking changes and adopting the recommended patterns.
16
+ Instructions for the agent to apply when migrating a Harper application to v5, covering all breaking changes and required code updates.
17
17
 
18
18
  ## When to Use
19
19
 
20
- Apply this rule when upgrading a Harper application from v4.x (or earlier) to v5, or when code written against older APIs behaves differently after a v5 upgrade — for example a record that can no longer be mutated, a query that returns stale data, or a `spawn` call that now throws. Harper v5 introduces breaking changes; applications built on documented APIs need the updates below, while code relying on undocumented behavior or timing may need broader review.
20
+ Apply this rule when upgrading an existing Harper application to v5, when encountering runtime errors related to renamed packages, changed APIs, or security restrictions introduced in v5, or when reviewing application code for v5 compatibility before deployment.
21
21
 
22
22
  ## How It Works
23
23
 
24
- 1. **Adopt the `harper` package name**: HarperDB is now Harper, and the package was renamed. Install the open source edition with `npm i -g harper` and the pro edition with `npm i -g @harperfast/harper-pro`. Update application imports from `harperdb` to `harper`:
24
+ 1. **Update the package import from `harperdb` to `harper`**: All application code must import from `harper` instead of `harperdb`.
25
25
 
26
26
  ```javascript
27
27
  import { tables } from 'harper';
28
28
  ```
29
29
 
30
- 2. **Opt in to install scripts when required**: Harper now installs packages with `--ignore-scripts` to guard against accidental script execution, a common security risk. If an application genuinely needs install scripts to run (for example to build native binaries), pass the `allowInstallScripts` option when deploying.
30
+ 2. **Enable `allowInstallScripts` if packages require install scripts**: Harper v5 uses `--ignore-scripts` by default when installing packages. If your application requires installation scripts (e.g., to install additional binaries), set the `allowInstallScripts` option when deploying.
31
31
 
32
- 3. **Update `Table.get` return-value handling**: `Table.get` now returns a plain, frozen record object rather than an instance of the table class, so instance methods are no longer available on the result. The commonly used `wasLoadedFromSource()` method is gone; cache-vs-origin information now lives on the request `target` as `target.loadedFromSource`. Pass a `RequestTarget` to `Table.get` and read the flag from it. Because the record is frozen, create a copy instead of mutating it in place.
32
+ 3. **Update `Table.get` usage — return value is now a frozen record object**: `Table.get` now returns a plain record object, not a table class instance. The record is frozen; you cannot mutate it directly.
33
+ - Replace `wasLoadedFromSource()` with `target.loadedFromSource`:
33
34
 
34
- 4. **Account for automatic transaction context**: With RocksDB, transactions are fully supported by the storage engine, and Harper v5 uses asynchronous context tracking to carry the current transaction across calls automatically. A nested `Table.get` now reads within the current transaction's snapshot, so it will not observe newly written data until you commit. Access the context through `getContext()` and either commit the current transaction (`getContext().transaction.commit()`) or run the read inside a fresh `transaction(...)` to see the latest data. This matters most for code executing outside the context of a Harper request.
35
+ ```javascript
36
+ // Old — remove this pattern:
37
+ const record = await Table.get(id);
38
+ if (record.wasLoadedFromSource()) { ... }
35
39
 
36
- 5. **Register spawnable commands**: Spawning processes is now tightly controlled. `spawn`, `exec`, and `execFile` may only run executables listed in the `applications.allowedSpawnCommands` configuration, and each call must pass a `name` in its `options` so that only a single named process is started across Harper's multiple threads. Use a distinct `name` when you deliberately need a separate process.
40
+ // New — use loadedFromSource on the target:
41
+ const target = new RequestTarget();
42
+ target.id = id;
43
+ const record = await Table.get(target);
44
+ if (target.loadedFromSource) {
45
+ // record was loaded from origin (not cache)
46
+ }
47
+ ```
37
48
 
38
- 6. **Return Response-like objects to set headers**: If a REST method returns an object with a `headers` property, Harper uses it as the response headers.
49
+ - Replace in-place mutation with object spread, since records are frozen:
39
50
 
40
- 7. **Replace `blob.save()`**: The `blob.save()` method has been removed. Pass the `saveBeforeCommit` flag in the options to the `Blob` constructor instead.
51
+ ```javascript
52
+ // Old — throws in v5:
53
+ const record = await Table.get(id);
54
+ record.property = 'changed';
41
55
 
42
- 8. **Configure the VM module loader**: v5 loads application modules through Node.js's VM module API, giving each application its own module cache and an application-scoped `harper` module. All of this is controlled by the `applications` section of `harperdb-config.yaml`:
43
- - `moduleLoader` — `vm-current-context` (default), `vm`, `native`, or `compartment`. The default shares intrinsics with Harper for best compatibility; choose `vm` only if you need per-application intrinsics, and `native` to disable the VM loader entirely (restores pre-v5 loading, but per-app `logger`/`config` context is unavailable).
44
- - `lockdown` — `freeze-after-load` (default), `freeze`, `ses`, or `none`. Freezing intrinsics prevents prototype-pollution attacks; set `lockdown: none` only as a temporary workaround if a dependency mutates built-in prototypes.
45
- - `allowedDirectory` — `app` (default) restricts module loading to the application's own directory tree; set `any` if the app must load files from outside it in production.
46
- - `allowedBuiltinModules` — an optional allowlist restricting which Node.js built-ins the application may import (all are allowed if omitted).
47
- - `dependencyLoader` — `auto` (default), `app`, or `native`, controlling how npm dependencies are loaded through or around the VM loader.
56
+ // New — copy instead of mutate:
57
+ let record = await Table.get(id);
58
+ record = { ...record, property: 'changed' };
59
+ ```
48
60
 
49
- ## Examples
61
+ - `getUpdatedTime` and `getExpiresAt` methods remain available on the record object.
50
62
 
51
- **Updating `Table.get` and its cache check:**
63
+ 4. **Update transaction and context handling**: Harper v5 uses asynchronous context tracking. `Table.get` and other table calls now automatically inherit the current transaction context. Code that previously omitted context to bypass a transaction will no longer work as expected. Use `getContext` (imported from `harper`) to access and commit the current transaction explicitly when you need to see updated data.
52
64
 
53
- ```javascript
54
- // Old (v4.x)
55
- const record = await Table.get(id);
56
- if (record.wasLoadedFromSource()) {
57
- // loaded from origin, not cache
58
- }
59
-
60
- // New (v5)
61
- const target = new RequestTarget(); // passed in when overriding `get`
62
- target.id = id;
63
- const record = await Table.get(target);
64
- if (target.loadedFromSource) {
65
- // loaded from origin, not cache
66
- }
67
- ```
65
+ ```javascript
66
+ import { setTimeout as delay } from 'node:timers/promises';
67
+ import { getContext, transaction } from 'harper';
68
+
69
+ class MyResource {
70
+ static async get(target) {
71
+ // Commit the current transaction to read latest data:
72
+ await getContext().transaction.commit();
73
+ // Optionally wrap each poll in a new transaction:
74
+ while ((await transaction(() => Table.get(target))).status !== 'ready') {
75
+ await delay(100);
76
+ }
77
+ return Table.get(target);
78
+ }
79
+ }
80
+ ```
68
81
 
69
- **Committing the transaction to read fresh data:**
82
+ 5. **Register allowed spawn commands via `allowedSpawnCommands`**: Any use of `spawn`, `exec`, or `execFile` from `node:child_process` must reference executables listed in `applications.allowedSpawnCommands` in `harperdb-config.yaml`. Provide a `name` property in the options argument to ensure only a single named process is started across threads.
70
83
 
71
- ```javascript
72
- import { setTimeout as delay } from 'node:timers/promises';
73
- import { getContext, transaction } from 'harper';
74
-
75
- class MyResource {
76
- static async get(target) {
77
- // The current transaction is a consistent snapshot; commit it to see updates.
78
- await getContext().transaction.commit();
79
- while ((await transaction(() => Table.get(target))).status !== 'ready') {
80
- delay(100);
81
- }
82
- return Table.get(target);
83
- }
84
- }
85
- ```
84
+ 6. **Replace `blob.save()` with `saveBeforeCommit`**: The `blob.save()` method has been removed. Use the `saveBeforeCommit` flag in the options passed to the `Blob` constructor instead.
86
85
 
87
- **Module loader and security configuration in `harperdb-config.yaml`:**
86
+ 7. **Configure the `moduleLoader` and `lockdown` settings**: Harper v5 loads application modules through Node.js's VM module API. Control this behavior in `harperdb-config.yaml` under the `applications` key.
87
+
88
+ | Setting | Default | Options |
89
+ | ------------------ | -------------------- | --------------------------------------------------- |
90
+ | `moduleLoader` | `vm-current-context` | `vm-current-context`, `vm`, `native`, `compartment` |
91
+ | `lockdown` | `freeze-after-load` | `freeze-after-load`, `freeze`, `ses`, `none` |
92
+ | `dependencyLoader` | `auto` | `auto`, `app`, `native` |
93
+ | `allowedDirectory` | `app` | `app`, `any` |
94
+ - Use `moduleLoader: native` to disable the VM loader entirely and restore pre-v5 behavior (application-specific context such as tagged logging and per-app `config` will not be available).
95
+ - Use `lockdown: none` as a temporary workaround if a dependency modifies intrinsic prototypes at runtime and throws a `TypeError`.
96
+
97
+ ## Examples
98
+
99
+ ### Full `harperdb-config.yaml` `applications` block
88
100
 
89
101
  ```yaml
90
102
  applications:
91
- lockdown: freeze-after-load # default
92
- moduleLoader: vm-current-context # vm-current-context (default) | vm | native | compartment
93
- dependencyLoader: auto # auto (default) | app | native
94
- allowedDirectory: app # app (default) | any
103
+ lockdown: freeze-after-load
104
+ moduleLoader: vm-current-context
105
+ dependencyLoader: auto
106
+ allowedDirectory: app
95
107
  allowedSpawnCommands:
96
108
  - npm
97
109
  - node
98
- # allowedBuiltinModules: [] # if omitted, all Node.js built-ins are allowed
99
110
  ```
100
111
 
101
- ## Recommended Changes
112
+ ### Restricting allowed built-in modules
113
+
114
+ ```yaml
115
+ applications:
116
+ allowedBuiltinModules:
117
+ - fs
118
+ - path
119
+ - http
120
+ ```
121
+
122
+ ### Disabling the VM loader for package compatibility
123
+
124
+ ```yaml
125
+ applications:
126
+ moduleLoader: native
127
+ ```
128
+
129
+ ### Accessing context and committing a transaction
130
+
131
+ ```javascript
132
+ import { getContext } from 'harper';
133
+
134
+ await getContext().transaction.commit();
135
+ ```
102
136
 
103
- Beyond the required fixes above, Harper v5 encourages these patterns for new and migrated code:
137
+ ## Notes
104
138
 
105
- - Implement endpoints with `static` methods on Resources/Tables, reading request information from the request `target` argument (or from `getContext()`).
106
- - Rely on automatic context propagation rather than threading context through every call manually; access it via `getContext()` exported from `harper`.
107
- - Access Harper functions and APIs through the `harper` package rather than through global variables.
139
+ - The `lockdown: freeze-after-load` default freezes `Object`, `Array`, `Promise`, `Map`, `Set`, and other intrinsics after all application code loads. Any code or dependency that mutates intrinsic prototypes after startup will throw a `TypeError`.
140
+ - Under `lockdown: ses`, the constrained `fetch` (https-only) is applied only in `vm` mode. In `vm-current-context` and `native` modes, application code uses the standard global `fetch`.
141
+ - In production, `allowedDirectory: app` prevents loading modules from outside the application's own directory tree. Set `allowedDirectory: any` only if your application legitimately requires it.
142
+ - `dependencyLoader: native` is a narrower alternative to `moduleLoader: native` — it uses native loading only for npm packages while keeping the VM loader for first-party application source files.
143
+ - Access Harper functions and APIs through the `harper` package rather than through global variables. Use `getContext` from `harper` to access request context without passing it explicitly through every call.