@harperfast/template-react-ts-studio 1.12.1 → 1.12.3
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/.agents/skills/harper-best-practices/AGENTS.md +672 -400
- package/.agents/skills/harper-best-practices/rules/automatic-apis.md +131 -55
- package/.agents/skills/harper-best-practices/rules/checking-authentication.md +155 -61
- package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +78 -48
- package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +111 -52
- package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +38 -70
- package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +81 -69
- package/.agents/skills/harper-best-practices/rules/v5-upgrade.md +108 -60
- package/.agents/skills/harper-best-practices/rules.manifest.yaml +212 -0
- package/agent/skills/harper-best-practices/AGENTS.md +672 -400
- package/agent/skills/harper-best-practices/rules/automatic-apis.md +131 -55
- package/agent/skills/harper-best-practices/rules/checking-authentication.md +155 -61
- package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +78 -48
- package/agent/skills/harper-best-practices/rules/programmatic-table-requests.md +111 -52
- package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +38 -70
- package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +81 -69
- package/agent/skills/harper-best-practices/rules/v5-upgrade.md +108 -60
- package/agent/skills/harper-best-practices/rules.manifest.yaml +212 -0
- package/package.json +1 -1
- package/skills-lock.json +1 -1
|
@@ -7,8 +7,8 @@ metadata:
|
|
|
7
7
|
mode: generate
|
|
8
8
|
sources:
|
|
9
9
|
- release-notes/v5-lincoln/v5-migration.md
|
|
10
|
-
sourceCommit:
|
|
11
|
-
inputHash:
|
|
10
|
+
sourceCommit: 677ad213d67822e109c83619e181ca23a59823db
|
|
11
|
+
inputHash: 01c0fafb9afa68a0
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# v5 Upgrade: Breaking Changes and Migration Guide
|
|
@@ -17,60 +17,53 @@ Instructions for the agent to apply when migrating a Harper application to v5, c
|
|
|
17
17
|
|
|
18
18
|
## When to Use
|
|
19
19
|
|
|
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
|
|
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 after a v5 upgrade, or when scaffolding new v5-compatible application code.
|
|
21
21
|
|
|
22
22
|
## How It Works
|
|
23
23
|
|
|
24
|
-
1. **Update the package import from `harperdb` to `harper`**: All application code must import from `harper
|
|
24
|
+
1. **Update the package import from `harperdb` to `harper`**: All application code must import from `harper`, not `harperdb`.
|
|
25
25
|
|
|
26
26
|
```javascript
|
|
27
27
|
import { tables } from 'harper';
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
2. **Enable `allowInstallScripts` if packages require install scripts**: Harper v5 uses `--ignore-scripts` by default when installing packages. If
|
|
30
|
+
2. **Enable `allowInstallScripts` if packages require install scripts**: Harper v5 uses `--ignore-scripts` by default when installing packages. If a package requires execution of install scripts (e.g., to install native binaries), set the `allowInstallScripts` option when deploying.
|
|
31
31
|
|
|
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
|
|
33
|
-
- Replace
|
|
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 add or mutate properties directly.
|
|
33
|
+
- Replace direct property mutation:
|
|
34
34
|
|
|
35
35
|
```javascript
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
let record = await Table.get(id);
|
|
37
|
+
record = { ...record, property: 'changed' };
|
|
38
|
+
```
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
- Replace `wasLoadedFromSource()` with `loadedFromSource` on the `target` object:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
41
43
|
const target = new RequestTarget();
|
|
42
44
|
target.id = id;
|
|
43
45
|
const record = await Table.get(target);
|
|
44
46
|
if (target.loadedFromSource) {
|
|
45
|
-
|
|
47
|
+
// record was loaded from origin (not cache)
|
|
46
48
|
}
|
|
47
49
|
```
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
The record objects still expose `getUpdatedTime` and `getExpiresAt` methods.
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
// Old — throws in v5:
|
|
53
|
-
const record = await Table.get(id);
|
|
54
|
-
record.property = 'changed';
|
|
53
|
+
4. **Update transaction and context handling using `getContext`**: Harper v5 uses asynchronous context tracking. Context and the current transaction are automatically carried to all downstream calls — you no longer pass context explicitly. Import `getContext` and `transaction` from `harper`:
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
- `getUpdatedTime` and `getExpiresAt` methods remain available on the record object.
|
|
55
|
+
```javascript
|
|
56
|
+
import { getContext, transaction } from 'harper';
|
|
57
|
+
```
|
|
62
58
|
|
|
63
|
-
|
|
59
|
+
If your code previously omitted context to escape a transaction (e.g., to poll for updated data), explicitly commit the transaction and/or wrap each read in a new `transaction()` call:
|
|
64
60
|
|
|
65
61
|
```javascript
|
|
66
62
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
67
63
|
import { getContext, transaction } from 'harper';
|
|
68
|
-
|
|
69
64
|
class MyResource {
|
|
70
65
|
static async get(target) {
|
|
71
|
-
// Commit the current transaction to read latest data:
|
|
72
66
|
await getContext().transaction.commit();
|
|
73
|
-
// Optionally wrap each poll in a new transaction:
|
|
74
67
|
while ((await transaction(() => Table.get(target))).status !== 'ready') {
|
|
75
68
|
await delay(100);
|
|
76
69
|
}
|
|
@@ -79,24 +72,90 @@ Apply this rule when upgrading an existing Harper application to v5, when encoun
|
|
|
79
72
|
}
|
|
80
73
|
```
|
|
81
74
|
|
|
82
|
-
5. **Register allowed spawn commands via `allowedSpawnCommands`**:
|
|
75
|
+
5. **Register allowed spawn commands via `allowedSpawnCommands`**: `spawn` and `execFile` may only launch executables listed in `applications.allowedSpawnCommands` in `harperdb-config.yaml`. Only the first token of the command is matched. `exec` is not usable through the substituted module; `execSync` always throws.
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
applications:
|
|
79
|
+
allowedSpawnCommands:
|
|
80
|
+
- npm
|
|
81
|
+
- node
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Additionally, `spawn`, `execFile`, and `fork` now require a `name` property in the `options` argument to prevent process multiplication across threads.
|
|
85
|
+
|
|
86
|
+
6. **Use `saveBeforeCommit` instead of `blob.save()`**: The `blob.save()` method has been removed. Pass the `saveBeforeCommit` flag in the options to the `Blob` constructor instead.
|
|
87
|
+
|
|
88
|
+
7. **Handle `headers` on returned response objects**: If you return an object from a REST method with a `headers` property, Harper v5 will use it as the response headers.
|
|
89
|
+
|
|
90
|
+
8. **Configure the VM module loader and `lockdown` in `harperdb-config.yaml`**: v5 loads application modules through Node.js's VM module API. Control all behavior under the `applications` key:
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
applications:
|
|
94
|
+
lockdown: freeze-after-load
|
|
95
|
+
moduleLoader: vm-current-context
|
|
96
|
+
dependencyLoader: auto
|
|
97
|
+
allowedDirectory: app
|
|
98
|
+
allowedSpawnCommands:
|
|
99
|
+
- npm
|
|
100
|
+
- node
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**`moduleLoader` options:**
|
|
104
|
+
|
|
105
|
+
| Value | Behavior |
|
|
106
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
107
|
+
| `vm-current-context` | Default. VM loader in Harper's own context; shares intrinsics with Harper. Best compatibility. |
|
|
108
|
+
| `vm` | VM loader in a separate per-application context with its own intrinsics. Stronger isolation but may cause `instanceof` failures. |
|
|
109
|
+
| `native` | Standard Node.js `import()`. No VM loader; application-specific context (`logger`, `config`) unavailable. |
|
|
110
|
+
| `compartment` | SES Compartment-based loading. For specialized sandboxing only. |
|
|
111
|
+
|
|
112
|
+
**`lockdown` options:**
|
|
83
113
|
|
|
84
|
-
|
|
114
|
+
| Value | Behavior |
|
|
115
|
+
| ------------------- | ------------------------------------------------------- |
|
|
116
|
+
| `freeze-after-load` | Default. Freezes intrinsics after all components load. |
|
|
117
|
+
| `freeze` | Freezes intrinsics before loading any application code. |
|
|
118
|
+
| `ses` | Full SES lockdown via the `ses` package. Strictest. |
|
|
119
|
+
| `none` | No lockdown. Use as a temporary workaround only. |
|
|
85
120
|
|
|
86
|
-
|
|
121
|
+
To disable the VM loader entirely and restore pre-v5 behavior:
|
|
87
122
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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`.
|
|
123
|
+
```yaml
|
|
124
|
+
applications:
|
|
125
|
+
moduleLoader: native
|
|
126
|
+
```
|
|
96
127
|
|
|
97
128
|
## Examples
|
|
98
129
|
|
|
99
|
-
|
|
130
|
+
**Full transaction polling pattern (v5):**
|
|
131
|
+
|
|
132
|
+
```javascript
|
|
133
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
134
|
+
import { getContext, transaction } from 'harper';
|
|
135
|
+
|
|
136
|
+
class MyResource {
|
|
137
|
+
static async get(target) {
|
|
138
|
+
await getContext().transaction.commit();
|
|
139
|
+
while ((await transaction(() => Table.get(target))).status !== 'ready') {
|
|
140
|
+
await delay(100);
|
|
141
|
+
}
|
|
142
|
+
return Table.get(target);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Checking `loadedFromSource` after `Table.get`:**
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
const target = new RequestTarget();
|
|
151
|
+
target.id = id;
|
|
152
|
+
const record = await Table.get(target);
|
|
153
|
+
if (target.loadedFromSource) {
|
|
154
|
+
// record was loaded from origin (not cache)
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Full `harperdb-config.yaml` `applications` block:**
|
|
100
159
|
|
|
101
160
|
```yaml
|
|
102
161
|
applications:
|
|
@@ -109,7 +168,7 @@ applications:
|
|
|
109
168
|
- node
|
|
110
169
|
```
|
|
111
170
|
|
|
112
|
-
|
|
171
|
+
**Restricting allowed built-in modules:**
|
|
113
172
|
|
|
114
173
|
```yaml
|
|
115
174
|
applications:
|
|
@@ -119,25 +178,14 @@ applications:
|
|
|
119
178
|
- http
|
|
120
179
|
```
|
|
121
180
|
|
|
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
|
-
```
|
|
136
|
-
|
|
137
181
|
## Notes
|
|
138
182
|
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
- `
|
|
143
|
-
-
|
|
183
|
+
- Always import Harper APIs from `'harper'`, not from global variables or `'harperdb'`.
|
|
184
|
+
- `getContext` is exported from `'harper'` and provides access to the current transaction without passing context explicitly.
|
|
185
|
+
- Record objects returned by `Table.get` are frozen — spread into a new object before modifying.
|
|
186
|
+
- `loadedFromSource` is a property on the `target` object, replacing the removed `wasLoadedFromSource()` instance method.
|
|
187
|
+
- `saveBeforeCommit` replaces the removed `blob.save()` method.
|
|
188
|
+
- The `headers` property on a returned REST response object is used as response headers.
|
|
189
|
+
- Under `lockdown: ses`, the constrained `fetch` applies only in `vm` mode. In `vm-current-context` and `native` modes, application code uses the standard global `fetch`.
|
|
190
|
+
- In production, `allowedDirectory: app` is the default; modules outside the application directory tree will throw. Set `allowedDirectory: any` only if legitimately required.
|
|
191
|
+
- `dependencyLoader: native` is a narrower option than `moduleLoader: native` — it uses native loading only for npm packages while keeping the VM loader for first-party application source files.
|
|
@@ -149,14 +149,61 @@ rules:
|
|
|
149
149
|
order: 1
|
|
150
150
|
mode: generate
|
|
151
151
|
sources:
|
|
152
|
+
# overview.md is sourced section-by-section rather than whole-file: at
|
|
153
|
+
# ~15KB it was the largest single input in the skill, and the compression
|
|
154
|
+
# dropped conditional requests, content negotiation, and the `GET`
|
|
155
|
+
# caveats outright. Listing sections narrows the input and makes a docs
|
|
156
|
+
# rename fail loudly in sliceSection. The dropped headings are the
|
|
157
|
+
# `# REST Overview` preamble (marketing + a version badge) and
|
|
158
|
+
# `## See Also` (link list); `## OpenAPI` is kept because the rule
|
|
159
|
+
# documents `GET /openapi`.
|
|
152
160
|
- path: reference/v5/rest/overview.md
|
|
161
|
+
section: 'How the REST Interface Works'
|
|
153
162
|
role: primary
|
|
163
|
+
- path: reference/v5/rest/overview.md
|
|
164
|
+
section: 'Configuration'
|
|
165
|
+
role: primary
|
|
166
|
+
- path: reference/v5/rest/overview.md
|
|
167
|
+
section: 'Tables and Their Automatic Endpoints'
|
|
168
|
+
role: primary
|
|
169
|
+
- path: reference/v5/rest/overview.md
|
|
170
|
+
section: 'URL Structure'
|
|
171
|
+
role: primary
|
|
172
|
+
- path: reference/v5/rest/overview.md
|
|
173
|
+
section: 'HTTP Methods'
|
|
174
|
+
role: primary
|
|
175
|
+
- path: reference/v5/rest/overview.md
|
|
176
|
+
section: 'Content Types'
|
|
177
|
+
role: primary
|
|
178
|
+
- path: reference/v5/rest/overview.md
|
|
179
|
+
section: 'OpenAPI'
|
|
180
|
+
role: supplemental
|
|
154
181
|
- path: reference/v5/rest/websockets.md
|
|
155
182
|
role: supplemental
|
|
156
183
|
must_cover:
|
|
157
184
|
- 'rest: true'
|
|
158
185
|
- '@export'
|
|
159
186
|
- 'WebSocket'
|
|
187
|
+
# Each of the following occurs exactly once across the sourced sections,
|
|
188
|
+
# so each pins one previously-dropped section:
|
|
189
|
+
# If-None-Match / 304 Not Modified → `#### Conditional Requests and Caching`
|
|
190
|
+
# `Accept` → `## Content Types` (bare `Accept`
|
|
191
|
+
# would be satisfied by the SSE `Accept: text/event-stream` mention
|
|
192
|
+
# under `## Tables and Their Automatic Endpoints`, which gates nothing)
|
|
193
|
+
# .msgpack → the reserved content-type selector
|
|
194
|
+
# suffixes and the undeclared-property caveat in `### GET`
|
|
195
|
+
- 'If-None-Match'
|
|
196
|
+
- '304 Not Modified'
|
|
197
|
+
- 'ETag'
|
|
198
|
+
- '`Accept`'
|
|
199
|
+
- '.msgpack'
|
|
200
|
+
# Pinned after the first regen dropped them while restoring the three
|
|
201
|
+
# sections above — an unanchored fact is only ever one regen from being
|
|
202
|
+
# compressed away, whichever fact it is:
|
|
203
|
+
# Location (2×) → the primary key POST returns in that header
|
|
204
|
+
# @updatedTime (1×) → the three exceptions PUT always applies
|
|
205
|
+
- 'Location'
|
|
206
|
+
- '@updatedTime'
|
|
160
207
|
cross_links:
|
|
161
208
|
- querying-rest-apis
|
|
162
209
|
- real-time-apps
|
|
@@ -207,13 +254,123 @@ rules:
|
|
|
207
254
|
- path: reference/v5/resources/resource-api.md
|
|
208
255
|
section: 'Session and Login from a Resource'
|
|
209
256
|
role: primary
|
|
257
|
+
# JWT half. Sectioned *and* anchored deliberately.
|
|
258
|
+
#
|
|
259
|
+
# The generator concatenates every resolved source into one unlabeled
|
|
260
|
+
# blob (lib/sources.mjs `resolveSources`) and the system prompt tells the
|
|
261
|
+
# model to "keep it tight" and omit tangential detail. So whatever no
|
|
262
|
+
# `must_cover` anchor requires is exactly what gets compressed away —
|
|
263
|
+
# anchor starvation, not source ordering or size. As a whole-file source
|
|
264
|
+
# with no JWT anchors, this half collapsed to a single "use JWT instead"
|
|
265
|
+
# pointer and lost the token issue/refresh flow entirely.
|
|
266
|
+
#
|
|
267
|
+
# `must_cover` is the actual gate: it is enforced verbatim
|
|
268
|
+
# (validate-generated.mjs, `body.includes(must)`) and is echoed to the
|
|
269
|
+
# model as a hard requirement. `section:` only narrows what gets fed in —
|
|
270
|
+
# it helps because it tends to come with anchors, not on its own. Prefer
|
|
271
|
+
# identifier-shaped anchors that occur in exactly one sourced section; an
|
|
272
|
+
# anchor matching many sections gates nothing in particular.
|
|
273
|
+
#
|
|
274
|
+
# `role:` is a human-facing annotation only — the generator never reads
|
|
275
|
+
# it (it is enum-checked by the validator and otherwise unused).
|
|
276
|
+
- path: reference/v5/security/jwt-authentication.md
|
|
277
|
+
section: 'Create Authentication Tokens'
|
|
278
|
+
role: primary
|
|
210
279
|
- path: reference/v5/security/jwt-authentication.md
|
|
280
|
+
section: 'Using the Operation Token'
|
|
281
|
+
role: supplemental
|
|
282
|
+
- path: reference/v5/security/jwt-authentication.md
|
|
283
|
+
section: 'Refreshing the Operation Token'
|
|
284
|
+
role: primary
|
|
285
|
+
- path: reference/v5/security/jwt-authentication.md
|
|
286
|
+
section: 'Scoped Tokens (Inline Role)'
|
|
287
|
+
role: primary
|
|
288
|
+
- path: reference/v5/security/jwt-authentication.md
|
|
289
|
+
section: 'Issuing Tokens from a Custom Resource'
|
|
290
|
+
role: primary
|
|
291
|
+
- path: reference/v5/security/jwt-authentication.md
|
|
292
|
+
section: 'Token Expiry Configuration'
|
|
293
|
+
role: supplemental
|
|
294
|
+
# Sourced so the rule carries the *negative* recommendation too. Without
|
|
295
|
+
# it the generated body pushed JWT at every non-browser client, while the
|
|
296
|
+
# source actually points simple and server-to-server callers at Basic
|
|
297
|
+
# Authentication — i.e. the rule was inviting token lifecycle complexity
|
|
298
|
+
# the docs tell you to avoid.
|
|
299
|
+
- path: reference/v5/security/jwt-authentication.md
|
|
300
|
+
section: 'When to Use JWT Auth'
|
|
301
|
+
role: primary
|
|
302
|
+
- path: reference/v5/security/jwt-authentication.md
|
|
303
|
+
section: 'Security Notes'
|
|
211
304
|
role: supplemental
|
|
212
305
|
must_cover:
|
|
306
|
+
# Session half.
|
|
213
307
|
- 'getCurrentUser()'
|
|
214
308
|
- 'getContext()'
|
|
215
309
|
- 'context.login'
|
|
216
310
|
- 'enableSessions'
|
|
311
|
+
# JWT half. One anchor per sourced section wherever an identifier is
|
|
312
|
+
# unique to it: `server.operation` pins the custom-resource section,
|
|
313
|
+
# `add_role`/`expires_in` the scoped-token section, `HTTPS` the security
|
|
314
|
+
# notes (`operationTokenTimeout` alone no longer distinguishes those two,
|
|
315
|
+
# since it occurs in both). `create_authentication_tokens` is the one
|
|
316
|
+
# unavoidably broad anchor — it is the subject of its own section but is
|
|
317
|
+
# back-referenced by three others, so it gates presence, not depth.
|
|
318
|
+
- 'create_authentication_tokens'
|
|
319
|
+
- 'refresh_operation_token'
|
|
320
|
+
- 'server.operation'
|
|
321
|
+
- 'add_role'
|
|
322
|
+
- 'expires_in'
|
|
323
|
+
- 'operationTokenTimeout'
|
|
324
|
+
- 'HTTPS'
|
|
325
|
+
# Scoped tokens are rejected with a 401 by nodes too old to understand
|
|
326
|
+
# them. Unanchored, that bullet was dropped the first time this rule was
|
|
327
|
+
# regenerated after the section was added — a rollout hazard, so it gets
|
|
328
|
+
# its own anchor rather than relying on the section being sourced.
|
|
329
|
+
- 'mixed-version'
|
|
330
|
+
# Operation names alone gate vocabulary, not mechanics: a regeneration
|
|
331
|
+
# could keep `create_authentication_tokens`/`refresh_operation_token` and
|
|
332
|
+
# still drop the token exchange, the refresh timeout, or what the third
|
|
333
|
+
# `server.operation` argument does. The anchors below pin those specific
|
|
334
|
+
# semantics. Each occurs exactly once in the doc and in exactly one
|
|
335
|
+
# sourced section, so it forces depth in that section rather than a
|
|
336
|
+
# passing mention anywhere.
|
|
337
|
+
#
|
|
338
|
+
# Two caveats this list is deliberately built around:
|
|
339
|
+
#
|
|
340
|
+
# 1. `must_cover` is a substring test (`body.includes(must)`), so an
|
|
341
|
+
# anchor contained in another anchor gates nothing extra.
|
|
342
|
+
# `operation_token` is already implied by `refresh_operation_token`,
|
|
343
|
+
# and `refresh_token` by `Bearer <refresh_token>` — listing either
|
|
344
|
+
# separately would be noise, not coverage.
|
|
345
|
+
# 2. A bare-fragment anchor invites literal satisfaction. Anchoring the
|
|
346
|
+
# exchange as `Bearer <refresh_token>` — rather than `refresh_token`,
|
|
347
|
+
# which occurs in three sourced sections — requires the body to show
|
|
348
|
+
# the refresh token actually being presented as the Bearer credential.
|
|
349
|
+
#
|
|
350
|
+
# `third argument` + `current authenticated user` pin the authorize
|
|
351
|
+
# behavior together. `authorize: true` is the doc's prose name for it but
|
|
352
|
+
# is rejected as an anchor: the code passes `true` positionally, so
|
|
353
|
+
# forcing that string risks a body an agent transcribes as an options
|
|
354
|
+
# object.
|
|
355
|
+
- 'Bearer <refresh_token>'
|
|
356
|
+
- 'refreshTokenTimeout'
|
|
357
|
+
- 'third argument'
|
|
358
|
+
- 'current authenticated user'
|
|
359
|
+
# When to Use JWT Auth. `Basic Authentication` is a superstring of the
|
|
360
|
+
# plain `Basic Auth` the section also contains — which is the better
|
|
361
|
+
# anchor, since `Basic Auth` additionally appears in a code comment in
|
|
362
|
+
# the custom-resource section and could be satisfied from there while the
|
|
363
|
+
# recommendation itself stayed compressed away. `server-to-server` pins
|
|
364
|
+
# the scenario the source actually steers away from JWT.
|
|
365
|
+
#
|
|
366
|
+
# `preferred over Basic Auth` carries the source's *conditional* framing.
|
|
367
|
+
# It is anchored because sourcing the section alone was not enough: the
|
|
368
|
+
# body kept a flat "for non-browser clients, use JWT" directive and filed
|
|
369
|
+
# the Basic Auth alternative under Notes, which reads as a contradiction.
|
|
370
|
+
# Anchoring the conditional forces the choice to be stated as a tradeoff.
|
|
371
|
+
- 'Basic Authentication'
|
|
372
|
+
- 'server-to-server'
|
|
373
|
+
- 'preferred over Basic Auth'
|
|
217
374
|
cross_links:
|
|
218
375
|
- custom-resources
|
|
219
376
|
|
|
@@ -293,6 +450,36 @@ rules:
|
|
|
293
450
|
- 'search('
|
|
294
451
|
- 'addTo'
|
|
295
452
|
- 'select'
|
|
453
|
+
# Query Object options that were covered before the transaction material
|
|
454
|
+
# was pinned, and that the regen then compressed out to make room. They
|
|
455
|
+
# are anchored now rather than left to survive on luck; each occurs only
|
|
456
|
+
# in § Query Object. `sort` also carries the `@indexed`-or-`conditions`
|
|
457
|
+
# requirement and `allowFullScan`, which have no meaning without it.
|
|
458
|
+
- 'sort'
|
|
459
|
+
- '@indexed'
|
|
460
|
+
- 'explain'
|
|
461
|
+
- 'enforceExecutionOrder'
|
|
462
|
+
# The `transaction(context?, callback)` source was already declared with a
|
|
463
|
+
# `section:` and was still dropped in full — proof that sectioning narrows
|
|
464
|
+
# the input but does not hold content in. Only an anchor does. Each of
|
|
465
|
+
# these occurs in exactly one sourced section:
|
|
466
|
+
# transaction() (2×) → § `transaction(context?, callback)`
|
|
467
|
+
# resetReadSnapshot() (1×) → its `### Transaction Object` member table
|
|
468
|
+
# atomicity (1×) → `### Transaction Scope and Atomicity`
|
|
469
|
+
# limit / offset (1× each) → § Query Object, the pagination pair
|
|
470
|
+
# Balanced parens deliberately: anchoring the bare `transaction(` also
|
|
471
|
+
# gates the section, but the model satisfies it literally and writes
|
|
472
|
+
# prose like "wrap background work in `transaction(`". `transaction()`
|
|
473
|
+
# contains `transaction(`, so it is the stricter anchor as well.
|
|
474
|
+
- 'transaction()'
|
|
475
|
+
- 'resetReadSnapshot()'
|
|
476
|
+
- 'atomicity'
|
|
477
|
+
- 'limit'
|
|
478
|
+
- 'offset'
|
|
479
|
+
# § Module Loading's one piece of actionable build guidance: keep `harper`
|
|
480
|
+
# external when bundling for SSR, or it is bundled instead of resolving
|
|
481
|
+
# to the runtime. Only occurrence of `vite.config` in the sources.
|
|
482
|
+
- 'vite.config'
|
|
296
483
|
|
|
297
484
|
- rule: typescript-type-stripping
|
|
298
485
|
description: How to run TypeScript files directly in Harper without a build step.
|
|
@@ -347,6 +534,28 @@ rules:
|
|
|
347
534
|
must_cover:
|
|
348
535
|
- 'harper deploy'
|
|
349
536
|
- 'harper login'
|
|
537
|
+
# `### Provisioning a Deploy Credential` is already inside the sourced
|
|
538
|
+
# `## Remote Management` slice, and its security guidance was compressed
|
|
539
|
+
# away anyway. These anchors pin it; each occurs only in that slice:
|
|
540
|
+
# fine-grained (2×) → prefer a fine-grained PAT over the `gh` CLI token
|
|
541
|
+
# read:org (1×) → the account-wide scopes the `gh` token carries
|
|
542
|
+
# enc:v1: (1×) → the client-side-encryption envelope
|
|
543
|
+
# They double as the rename detector for that subheading: if it is
|
|
544
|
+
# retitled or removed, the content goes and these anchors fail.
|
|
545
|
+
- 'fine-grained'
|
|
546
|
+
- 'Contents: Read-only'
|
|
547
|
+
- 'read:org'
|
|
548
|
+
- 'enc:v1:'
|
|
549
|
+
# Pinned after the first regen dropped it while restoring the credential
|
|
550
|
+
# guidance: `refs/heads/*` and `refs/tags/*` (or a bare branch/tag) are
|
|
551
|
+
# the only refs a `by_ref` deploy can fetch.
|
|
552
|
+
- 'refs/tags'
|
|
553
|
+
# Also pinned after a regen dropped it: `setup=true` calls
|
|
554
|
+
# `get_secrets_public_key` / `set_secret` / `grant_secret`, so it must be
|
|
555
|
+
# run with an administrative credential, not the CI identity it
|
|
556
|
+
# provisions for. The source escapes it as `super\_user`; every generated
|
|
557
|
+
# body so far unescapes, so the anchor is the unescaped form.
|
|
558
|
+
- 'super_user'
|
|
350
559
|
cross_links:
|
|
351
560
|
- creating-a-fabric-account-and-cluster
|
|
352
561
|
|
|
@@ -422,6 +631,9 @@ rules:
|
|
|
422
631
|
- 'moduleLoader'
|
|
423
632
|
- 'lockdown'
|
|
424
633
|
- 'Table.get'
|
|
634
|
+
# `## Response Objects` had no anchor and was dropped in full. Every
|
|
635
|
+
# occurrence of `headers` in the whole-file source is in that section.
|
|
636
|
+
- 'headers'
|
|
425
637
|
|
|
426
638
|
- rule: delegating-to-the-built-in-agent
|
|
427
639
|
description: How to delegate tasks to Harper's built-in agent via the CLI and the agent operations API.
|