@harperfast/template-react-ts-studio 1.12.2 → 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 +632 -474
- 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 +63 -85
- 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 +82 -96
- package/.agents/skills/harper-best-practices/rules.manifest.yaml +212 -0
- package/agent/skills/harper-best-practices/AGENTS.md +632 -474
- 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 +63 -85
- 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 +82 -96
- package/agent/skills/harper-best-practices/rules.manifest.yaml +212 -0
- package/package.json +1 -1
- package/skills-lock.json +1 -1
|
@@ -7,17 +7,17 @@ metadata:
|
|
|
7
7
|
mode: generate
|
|
8
8
|
sources:
|
|
9
9
|
- release-notes/v5-lincoln/v5-migration.md
|
|
10
|
-
sourceCommit:
|
|
10
|
+
sourceCommit: 677ad213d67822e109c83619e181ca23a59823db
|
|
11
11
|
inputHash: 01c0fafb9afa68a0
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# v5 Upgrade: Breaking Changes and Migration Guide
|
|
15
15
|
|
|
16
|
-
Instructions for the agent to apply
|
|
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
|
|
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
|
|
|
@@ -27,22 +27,20 @@ Apply this rule whenever upgrading an existing Harper application to v5, encount
|
|
|
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
|
|
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
|
-
if (record.wasLoadedFromSource()) {
|
|
39
|
-
// record was loaded from origin (not cache)
|
|
40
|
-
}
|
|
36
|
+
let record = await Table.get(id);
|
|
37
|
+
record = { ...record, property: 'changed' };
|
|
41
38
|
```
|
|
42
39
|
|
|
40
|
+
- Replace `wasLoadedFromSource()` with `loadedFromSource` on the `target` object:
|
|
41
|
+
|
|
43
42
|
```javascript
|
|
44
|
-
|
|
45
|
-
const target = new RequestTarget(); // note that this is passed in if you are overriding the `get` method
|
|
43
|
+
const target = new RequestTarget();
|
|
46
44
|
target.id = id;
|
|
47
45
|
const record = await Table.get(target);
|
|
48
46
|
if (target.loadedFromSource) {
|
|
@@ -50,107 +48,86 @@ Apply this rule whenever upgrading an existing Harper application to v5, encount
|
|
|
50
48
|
}
|
|
51
49
|
```
|
|
52
50
|
|
|
53
|
-
|
|
51
|
+
The record objects still expose `getUpdatedTime` and `getExpiresAt` methods.
|
|
54
52
|
|
|
55
|
-
|
|
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`:
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
record.property = 'changed';
|
|
61
|
-
```
|
|
55
|
+
```javascript
|
|
56
|
+
import { getContext, transaction } from 'harper';
|
|
57
|
+
```
|
|
62
58
|
|
|
63
|
-
|
|
64
|
-
// NEW
|
|
65
|
-
let record = await Table.get(id);
|
|
66
|
-
record = { ...record, property: 'changed' };
|
|
67
|
-
```
|
|
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:
|
|
68
60
|
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
```javascript
|
|
62
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
63
|
+
import { getContext, transaction } from 'harper';
|
|
64
|
+
class MyResource {
|
|
65
|
+
static async get(target) {
|
|
66
|
+
await getContext().transaction.commit();
|
|
67
|
+
while ((await transaction(() => Table.get(target))).status !== 'ready') {
|
|
68
|
+
await delay(100);
|
|
69
|
+
}
|
|
70
|
+
return Table.get(target);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
import { getContext, transaction } from 'harper';
|
|
74
|
-
```
|
|
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.
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
```yaml
|
|
78
|
+
applications:
|
|
79
|
+
allowedSpawnCommands:
|
|
80
|
+
- npm
|
|
81
|
+
- node
|
|
82
|
+
```
|
|
77
83
|
|
|
78
|
-
|
|
79
|
-
import { setTimeout as delay } from 'node:timers/promises';
|
|
80
|
-
import { getContext, transaction } from 'harper';
|
|
81
|
-
class MyResource {
|
|
82
|
-
static async get(target) {
|
|
83
|
-
await getContext().transaction.commit();
|
|
84
|
-
while ((await transaction(() => Table.get(target))).status !== 'ready') {
|
|
85
|
-
await delay(100);
|
|
86
|
-
}
|
|
87
|
-
return Table.get(target);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
```
|
|
84
|
+
Additionally, `spawn`, `execFile`, and `fork` now require a `name` property in the `options` argument to prevent process multiplication across threads.
|
|
91
85
|
|
|
92
|
-
|
|
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.
|
|
93
87
|
|
|
94
|
-
|
|
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.
|
|
95
89
|
|
|
96
|
-
|
|
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:
|
|
97
91
|
|
|
98
92
|
```yaml
|
|
99
93
|
applications:
|
|
100
|
-
lockdown: freeze-after-load
|
|
101
|
-
moduleLoader: vm-current-context
|
|
102
|
-
dependencyLoader: auto
|
|
103
|
-
allowedDirectory: app
|
|
104
|
-
allowedSpawnCommands:
|
|
94
|
+
lockdown: freeze-after-load
|
|
95
|
+
moduleLoader: vm-current-context
|
|
96
|
+
dependencyLoader: auto
|
|
97
|
+
allowedDirectory: app
|
|
98
|
+
allowedSpawnCommands:
|
|
105
99
|
- npm
|
|
106
100
|
- node
|
|
107
|
-
# allowedBuiltinModules: [] # if omitted, all Node.js built-ins are allowed
|
|
108
101
|
```
|
|
109
102
|
|
|
110
103
|
**`moduleLoader` options:**
|
|
111
104
|
|
|
112
105
|
| Value | Behavior |
|
|
113
106
|
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
114
|
-
| `vm-current-context` | Default. VM loader in Harper's own context; shares intrinsics with Harper
|
|
115
|
-
| `vm` | VM loader in a separate per-application context with its own intrinsics
|
|
116
|
-
| `native` | Standard Node.js `import()
|
|
117
|
-
| `compartment` | SES Compartment-based loading
|
|
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. |
|
|
118
111
|
|
|
119
112
|
**`lockdown` options:**
|
|
120
113
|
|
|
121
|
-
| Value | Behavior
|
|
122
|
-
| ------------------- |
|
|
123
|
-
| `freeze-after-load` | Default. Freezes intrinsics after all components
|
|
124
|
-
| `freeze` | Freezes intrinsics before loading any application code.
|
|
125
|
-
| `ses` | Full SES lockdown via the `ses` package
|
|
126
|
-
| `none` | No lockdown. Use as a temporary workaround only.
|
|
127
|
-
- To disable the VM loader entirely and restore pre-v5 behavior:
|
|
128
|
-
|
|
129
|
-
```yaml
|
|
130
|
-
applications:
|
|
131
|
-
moduleLoader: native
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
- To restrict which Node.js built-ins are accessible:
|
|
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. |
|
|
135
120
|
|
|
136
|
-
|
|
137
|
-
applications:
|
|
138
|
-
allowedBuiltinModules:
|
|
139
|
-
- fs
|
|
140
|
-
- path
|
|
141
|
-
- http
|
|
142
|
-
```
|
|
121
|
+
To disable the VM loader entirely and restore pre-v5 behavior:
|
|
143
122
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
allowedDirectory: any
|
|
149
|
-
```
|
|
123
|
+
```yaml
|
|
124
|
+
applications:
|
|
125
|
+
moduleLoader: native
|
|
126
|
+
```
|
|
150
127
|
|
|
151
128
|
## Examples
|
|
152
129
|
|
|
153
|
-
**Full transaction
|
|
130
|
+
**Full transaction polling pattern (v5):**
|
|
154
131
|
|
|
155
132
|
```javascript
|
|
156
133
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
@@ -158,9 +135,7 @@ import { getContext, transaction } from 'harper';
|
|
|
158
135
|
|
|
159
136
|
class MyResource {
|
|
160
137
|
static async get(target) {
|
|
161
|
-
// Explicitly commit the transaction to see updated data
|
|
162
138
|
await getContext().transaction.commit();
|
|
163
|
-
// Start a new transaction for each get to see the latest data
|
|
164
139
|
while ((await transaction(() => Table.get(target))).status !== 'ready') {
|
|
165
140
|
await delay(100);
|
|
166
141
|
}
|
|
@@ -169,11 +144,9 @@ class MyResource {
|
|
|
169
144
|
}
|
|
170
145
|
```
|
|
171
146
|
|
|
172
|
-
|
|
147
|
+
**Checking `loadedFromSource` after `Table.get`:**
|
|
173
148
|
|
|
174
149
|
```javascript
|
|
175
|
-
import { tables } from 'harper';
|
|
176
|
-
|
|
177
150
|
const target = new RequestTarget();
|
|
178
151
|
target.id = id;
|
|
179
152
|
const record = await Table.get(target);
|
|
@@ -195,11 +168,24 @@ applications:
|
|
|
195
168
|
- node
|
|
196
169
|
```
|
|
197
170
|
|
|
171
|
+
**Restricting allowed built-in modules:**
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
applications:
|
|
175
|
+
allowedBuiltinModules:
|
|
176
|
+
- fs
|
|
177
|
+
- path
|
|
178
|
+
- http
|
|
179
|
+
```
|
|
180
|
+
|
|
198
181
|
## Notes
|
|
199
182
|
|
|
200
|
-
-
|
|
201
|
-
-
|
|
202
|
-
-
|
|
203
|
-
- `
|
|
204
|
-
-
|
|
205
|
-
-
|
|
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.
|