@harperfast/template-react-ts-ssr-studio 1.13.4 → 1.13.6

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 +687 -453
  2. package/.agents/skills/harper-best-practices/SKILL.md +24 -21
  3. package/.agents/skills/harper-best-practices/rules/adding-tables-with-schemas.md +2 -0
  4. package/.agents/skills/harper-best-practices/rules/automatic-apis.md +2 -0
  5. package/.agents/skills/harper-best-practices/rules/caching.md +2 -0
  6. package/.agents/skills/harper-best-practices/rules/checking-authentication.md +2 -0
  7. package/.agents/skills/harper-best-practices/rules/custom-resources.md +2 -0
  8. package/.agents/skills/harper-best-practices/rules/defining-relationships.md +102 -40
  9. package/.agents/skills/harper-best-practices/rules/deploying-from-ci.md +121 -93
  10. package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +149 -103
  11. package/.agents/skills/harper-best-practices/rules/extending-tables.md +2 -0
  12. package/.agents/skills/harper-best-practices/rules/handling-binary-data.md +2 -0
  13. package/.agents/skills/harper-best-practices/rules/load-env.md +2 -0
  14. package/.agents/skills/harper-best-practices/rules/logging.md +2 -0
  15. package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +124 -91
  16. package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +86 -82
  17. package/.agents/skills/harper-best-practices/rules/real-time-apps.md +2 -0
  18. package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +92 -59
  19. package/.agents/skills/harper-best-practices/rules/serving-web-content.md +2 -0
  20. package/.agents/skills/harper-best-practices/rules/typescript-type-stripping.md +2 -0
  21. package/.agents/skills/harper-best-practices/rules/using-blob-datatype.md +2 -0
  22. package/.agents/skills/harper-best-practices/rules/vector-indexing.md +2 -0
  23. package/.agents/skills/harper-best-practices/rules.manifest.yaml +44 -0
  24. package/agent/skills/harper-best-practices/AGENTS.md +687 -453
  25. package/agent/skills/harper-best-practices/SKILL.md +26 -21
  26. package/agent/skills/harper-best-practices/rules/adding-tables-with-schemas.md +2 -0
  27. package/agent/skills/harper-best-practices/rules/automatic-apis.md +2 -0
  28. package/agent/skills/harper-best-practices/rules/caching.md +2 -0
  29. package/agent/skills/harper-best-practices/rules/checking-authentication.md +2 -0
  30. package/agent/skills/harper-best-practices/rules/custom-resources.md +2 -0
  31. package/agent/skills/harper-best-practices/rules/defining-relationships.md +102 -40
  32. package/agent/skills/harper-best-practices/rules/deploying-from-ci.md +121 -93
  33. package/agent/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +149 -103
  34. package/agent/skills/harper-best-practices/rules/extending-tables.md +2 -0
  35. package/agent/skills/harper-best-practices/rules/handling-binary-data.md +2 -0
  36. package/agent/skills/harper-best-practices/rules/load-env.md +2 -0
  37. package/agent/skills/harper-best-practices/rules/logging.md +2 -0
  38. package/agent/skills/harper-best-practices/rules/programmatic-table-requests.md +124 -91
  39. package/agent/skills/harper-best-practices/rules/querying-rest-apis.md +86 -82
  40. package/agent/skills/harper-best-practices/rules/real-time-apps.md +2 -0
  41. package/agent/skills/harper-best-practices/rules/schema-design-tooling.md +92 -59
  42. package/agent/skills/harper-best-practices/rules/serving-web-content.md +2 -0
  43. package/agent/skills/harper-best-practices/rules/typescript-type-stripping.md +2 -0
  44. package/agent/skills/harper-best-practices/rules/using-blob-datatype.md +2 -0
  45. package/agent/skills/harper-best-practices/rules/vector-indexing.md +2 -0
  46. package/agent/skills/harper-best-practices/rules.manifest.yaml +44 -0
  47. package/package.json +1 -1
  48. package/skills-lock.json +1 -1
@@ -23,17 +23,19 @@ metadata:
23
23
  - reference/v5/operations-api/operations.md#Retrying an activation
24
24
  - reference/v5/operations-api/operations.md#`list_deployments`
25
25
  - reference/v5/operations-api/operations.md#`get_job`
26
- sourceCommit: 81c1b0e8ce8da147a662f2ead72ce0c8769d0177
27
- inputHash: 899b47f26b8dca34
26
+ sourceCommit: e69702c99845f2dd810cb32652d1a9e6b58c538b
27
+ inputHash: 44ee050eac4a5056
28
28
  ---
29
29
 
30
30
  # Deploying to Harper Fabric
31
31
 
32
- Instructions for the agent to follow when deploying a Harper application to a Harper Fabric cluster, or any remote Harper instance, with the `harper` CLI, and when checking, staging, or going back to a release.
32
+ Instructions for the agent to deploy a Harper application to Harper Fabric using the CLI, verify certification, and roll back using a previous release's `deployment_id`.
33
+
34
+ **Instead of:** Docker Compose stacks; deploying several services separately. Use this rule rather than adding that service. See `harper-architecture`.
33
35
 
34
36
  ## When to Use
35
37
 
36
- Apply this rule when deploying to a remote cluster, choosing how it restarts, reading a deploy's `certification`, staging a release to make live later, or rolling back to a previous release. To deploy from CI with no stored credential, see [deploying-from-ci.md](deploying-from-ci.md). To set up the cluster first, see [creating-a-fabric-account-and-cluster.md](creating-a-fabric-account-and-cluster.md).
38
+ Apply this rule when deploying a Harper application to a remote Harper Fabric cluster, checking whether a rolling deploy was certified on each node, or restoring a previous release without rebuilding. Also apply it when provisioning credentials for private-source deploys or staging a build for later activation.
37
39
 
38
40
  ## How It Works
39
41
 
@@ -44,10 +46,9 @@ Apply this rule when deploying to a remote cluster, choosing how it restarts, re
44
46
  # Provide cluster username and password when prompted
45
47
  ```
46
48
 
47
- - For CI/CD on GitHub Actions, use workload identity (OIDC) instead, so the pipeline stores no Harper credential. From v5.4.0, `harper deploy setup=true provider=github-actions` sets it up in one command: see [deploying-from-ci.md](deploying-from-ci.md). Elsewhere, give the pipeline a refresh token from `harper login --for-ci` rather than a password.
48
- - For a one-off command, `auth_username=` and `auth_password=` also work, and take precedence over environment variables and saved login tokens. Don't use them in production.
49
+ For CI/CD pipelines, use workload identity (OIDC) or a refresh token from `harper login --for-ci` instead of a password. See [deploying-from-ci.md](deploying-from-ci.md) for a complete GitHub Actions workflow. For a one-off command, `auth_username=` and `auth_password=` also work, and take precedence over environment variables and saved login tokens. Don't use them in production.
49
50
 
50
- 2. **Deploy with a restart**: Run `harper deploy`, with `restart=true` or `restart=rolling` so the release is certified before it serves (step 3).
51
+ 2. **Deploy the application**: Run `harper deploy` with the required parameters. Omit `package` to upload the current directory; supply a reference for npm, GitHub, or tarball sources.
51
52
 
52
53
  ```bash
53
54
  harper deploy \
@@ -58,54 +59,38 @@ Apply this rule when deploying to a remote cluster, choosing how it restarts, re
58
59
  replicated=true
59
60
  ```
60
61
 
61
- - On Harper Pro and Fabric, a deploy goes to every node in the cluster unless you pass `replicated=false`. Harper core on its own does not replicate.
62
- - `project` defaults to the current directory's name for a directory deploy, or is derived from the package for a package deploy.
63
- - A bare `target` host defaults to `https://<host>:9925`.
64
- - Pass `json=true` to print the result as JSON instead of YAML.
65
- - Every result carries a `deployment_id`, staged or not. It names this release when you go back to it later (step 4).
66
-
67
- 3. **Choose the restart, and read `certification`**: `restart=true` restarts Harper after deploying. On a cluster, use `restart=rolling`, the staggered, zero-downtime restart: the command exits `0` once the node you called has taken the release and started the rolling restart's job, and returns its `restartJobId`.
68
-
69
- Both certify the release in a canary worker before rolling it out. The canary replaces worker 0 and loads every component, but is held out of traffic until it reports whether the deployed component loaded. Until then, the workers already running keep serving the previous release. A deploy that succeeds, and is not staged, reports the result in `certification`:
70
-
71
- | `certification` | Meaning |
72
- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
73
- | `certified` | The canary loaded the release, and the rollout went on. |
74
- | `uncertified` | The rollout went on unchecked: the component ran nothing as it loaded (`loadComponent: dev-only`, an absent `if-installed` component, or safe mode), or no worker was replaced. |
75
- | `unavailable` | The deploy restarted unchecked: no worker on this node loads the component, its `isolated` setting changed, it was already live, or it was deployed from a local directory (`package: file:<dir>`). |
76
- | `not-requested` | The deploy did not restart. |
77
- - **A rejected release fails the deploy.** If the canary throws while loading the component, exits, or doesn't report within a minute, the deploy fails with `400`. The release it replaced is made live again, and nothing is replicated to other nodes. The error's `certification` is an object whose `status` is `rejected`, or `interrupted` for a restart that stopped before the canary decided.
78
- - **A release with nothing to go back to fails closed.** A rejected first deploy, or one whose previous release was not kept, stays on disk, but no worker on that node loads it, even after Harper restarts. `get_status` reports the component as failed. Deploy a fix, or once the cause is fixed, activate the same `deployment_id` again with `restart`.
79
- - **A rolling deploy exits before every node has taken the release.** The other nodes stage it, and the job activates it on each in turn, each with a canary of its own. A node that rejects it keeps the previous release, or fails closed if it had none. Nothing is rolled back on the others, and the job fails naming each node that did not activate it. The deployment record reports `success` while the job runs and after it fails, so poll the job instead: `harper get_job id=<restartJobId>` ends `COMPLETE`, or `ERROR` with a `message` listing each node's outcome under `activated`.
80
- - **Poll the node that received the deploy.** A job is recorded only on the node that ran it, so any other node answers `get_job` with an empty array. A role with an `operations` allowlist, or a token with an `operations` scope, must list `get_job` to poll it.
81
- - Another deploy or `drop_component` of the component on that node is refused with `409` until the rollout has finished.
82
- - A node running a version before v5.4.0 activates the release without a canary.
62
+ A bare `target` host defaults to `https://<host>:9925`. Use `restart=rolling` for a staggered, zero-downtime restart across the cluster. Pass `replicated=false` to deploy only to the node you called. Pass `json=true` to print the result as JSON instead of YAML.
83
63
 
84
- 4. **Go back to a previous release by its `deployment_id`**: When a deploy replaces the live release, Harper keeps the replaced one under the `deployment_id` that deployed it. Activating that id puts back the exact installed release with no fetch, rebuild, or reinstall, where deploying an older commit installs it again from source. Find the id with `list_deployments`, then deploy it. On a cluster, restart with `rolling` and poll its job (step 3):
64
+ 3. **Choose a package source**: The `package` field accepts any valid npm dependency value.
65
+
66
+ | Source | Value |
67
+ | ------------------ | --------------------------------------------------------------------------------------------- |
68
+ | npm package | `package="@harperdb/status-check"` |
69
+ | GitHub (public) | `package="HarperFast/status-check"` or `package="https://github.com/HarperFast/status-check"` |
70
+ | Private repo (SSH) | `package="git+ssh://git@github.com:HarperDB/secret-app.git"` |
71
+ | Tarball | `package="https://example.com/application.tar.gz"` |
72
+
73
+ For git tags, use the `semver` directive: `HarperFast/application-template#semver:v1.0.0`. For an SSH-based private repo, register the key with `add_ssh_key` first.
74
+
75
+ 4. **Provision credentials for private repositories**: Run `harper deploy setup=true` once per component and source. (With `provider=github-actions`, it sets up GitHub Actions OIDC deploys instead.) This requires `super_user` privileges and is interactive. It calls `get_secrets_public_key`, `set_secret`, and `grant_secret`. Run it with an administrative credential rather than the CI identity it provisions for:
85
76
 
86
77
  ```bash
87
- harper list_deployments project=my-app status=success
88
- harper deploy project=my-app deployment_id=<id> restart=rolling
78
+ harper deploy setup=true
89
79
  ```
90
80
 
91
- ```json
92
- {
93
- "operation": "deploy_component",
94
- "project": "my-app",
95
- "deployment_id": "<id of the deployment you want back>",
96
- "restart": "rolling"
97
- }
98
- ```
81
+ The command:
82
+ 1. Fetches the cluster's public key with `get_secrets_public_key`.
83
+ 2. Encrypts the token locally into an `enc:v1:` envelope.
84
+ 3. Stores only the ciphertext with `set_secret`, scoped to the component, never in the global `processEnv` tier.
85
+ 4. Grants the component permission to resolve it with `grant_secret`.
99
86
 
100
- - `list_deployments` returns records newest first. Filter by `project` and `status`; omit `limit` to return every matching record. A deploy in progress reads `pending`, or `loading`, until its `completed_at` is set.
101
- - The newest `success` is not necessarily the release every node is serving: a rolling deploy's record says `success` before the other nodes have taken the release, and keeps saying it if one rejects it.
102
- - Redeploy an older commit by `ref` (step 7) only when the release is no longer kept.
103
- - The activation restores the root config entry that deployment published. The release it replaces is kept in turn, so you can go forward again the same way.
104
- - Kept releases and staged builds count against `deployment.stagingRetention.maxCount` (default `5`). Each kept release is a full installed copy of the component, `node_modules` included, so budget disk for it. `0` keeps no replaced release.
105
- - A release made live before v5.3.0, or deployed from a `file:` directory, is not kept.
106
- - Each node answers for itself. A node that never had the release, or no longer keeps it, answers `404`, which `deploy_component` reports as a failed peer. `409` means the build is there but can't be activated.
87
+ Use a **fine-grained** personal access token with **Contents: Read-only** on the target repository. Avoid broad tokens: the `gh` CLI session token typically carries `read:org`, `gist`, and `workflow` scopes across your whole account. Then deploy with `credential=true`:
88
+
89
+ ```bash
90
+ harper deploy by_ref=true credential=true restart=true replicated=true
91
+ ```
107
92
 
108
- 5. **Stage a release to make live later**: `activate=false` (`activate: false` in the operation) builds and installs the release on each node without making it live, so the slow, fallible part happens when you choose and the cut-over is quick. The result's `deployment_id` names the staged build:
93
+ 5. **Stage a release to make live later**: `activate=false` (`activate: false` in the operation) builds and installs the release on each node without making it live, so the slow, fallible part happens when you choose and the cut-over is quick. Cannot be combined with `restart`.
109
94
 
110
95
  ```json
111
96
  {
@@ -116,6 +101,8 @@ Apply this rule when deploying to a remote cluster, choosing how it restarts, re
116
101
  }
117
102
  ```
118
103
 
104
+ The response names the artifact waiting to be activated:
105
+
119
106
  ```json
120
107
  {
121
108
  "deployment_id": "a3f8c2d1-...",
@@ -123,99 +110,158 @@ Apply this rule when deploying to a remote cluster, choosing how it restarts, re
123
110
  }
124
111
  ```
125
112
 
126
- Make it live by deploying that `deployment_id`, as in step 4. Nothing changes until then, and `get_deployment` reports it as `staged`.
127
- - Pass `restart` on the activation, not the stage: `restart` is rejected alongside `activate: false`.
128
- - The activation takes no `package`, `payload`, `credentials`, install options, or `urlPath`/`host`. They are rejected, because the staged build already decided them.
129
- - Activating the release that is already live succeeds without a swap, so if an activation fails partway (a peer was unreachable, or the root config entry wasn't written), retry the same `deployment_id`. A node that already switched answers success, one still holding the build switches now, and one that holds neither answers `404`; the retry also finishes what the failed attempt left half done. With `restart`, a node where the release is already live still restarts every worker, isolated applications' included. Without it, the node marks the component as needing a restart.
130
- - A staged build outlives later deploys: stage v2, deploy v3, and activating v2's id returns the component to v2.
131
- - `file:` directory sources cannot be staged.
132
- - Upgrade every node before staging. A node before v5.3.0 doesn't recognize `activate: false`, and serves the release immediately. A peer that doesn't confirm staging fails the operation with the node names.
113
+ Nothing about the running component changes, and `get_deployment` reports it as `staged`. Make it live by deploying that `deployment_id`, as in step 6. The activation takes no `package`, `payload`, `credentials`, install options, or `urlPath`/`host`. They are rejected, because the staged build already decided them.
133
114
 
134
- 6. **Choose a package source**: The `package` field accepts any valid npm dependency value:
115
+ 6. **Activate a staged build or roll back**: Pass `deployment_id` with `restart` to make a staged build live, or to restore a release a later deploy replaced, with no rebuild or reinstall. Pass `restart` here rather than on the stage.
135
116
 
136
- | Source | `package` value |
137
- | ----------------------- | --------------------------------------------------------------------------------------------- |
138
- | Current local directory | Omit `package` |
139
- | npm package | `package="@harperdb/status-check"` |
140
- | GitHub (public) | `package="HarperFast/status-check"` or `package="https://github.com/HarperFast/status-check"` |
141
- | Private repo (SSH) | `package="git+ssh://git@github.com:HarperDB/secret-app.git"` |
142
- | Tarball | `package="https://example.com/application.tar.gz"` |
117
+ ```bash
118
+ harper deploy project=<name> deployment_id=<id> restart=true
119
+ ```
143
120
 
144
- For git tags, use the `semver` directive: `HarperFast/application-template#semver:v1.0.0`. For an SSH-based private repo, register the key with `add_ssh_key` first.
121
+ Use `list_deployments` to find the `deployment_id` of the release to restore:
145
122
 
146
- 7. **Deploy by reference for a reproducible source**: `by_ref=true` sends a pinned git reference instead of uploading the working directory, and the cluster fetches and builds that exact commit. It resolves the repository's `origin` remote and the current commit, then deploys `package=git+https://github.com/<owner>/<repo>.git#<full commit SHA>`. Pass `ref` to deploy a specific tag or commit instead of `HEAD`; it implies `by_ref`.
123
+ ```json
124
+ { "operation": "list_deployments", "project": "my-app", "status": "success", "limit": 20 }
125
+ ```
126
+
127
+ - A `404` response means the id never existed on that node, was pruned, or the release was replaced and not kept. A `409` means the build exists but cannot be activated (e.g., belongs to another component, or files changed after staging).
128
+ - Kept releases and staged builds count against `deployment.stagingRetention.maxCount` (`stagingRetention` default: `5`). Each kept release is a full installed copy of the component, `node_modules` included, so budget disk for it. `0` keeps no replaced releases.
129
+
130
+ 7. **Deploy by reference for a reproducible source**: `by_ref=true` sends a pinned git reference instead of uploading the working directory, and the cluster fetches and builds that exact commit. It resolves the repository's `origin` remote and the current commit, then deploys `package=git+https://github.com/<owner>/<repo>.git#<full commit SHA>`. Defaults to `HEAD`.
147
131
 
148
132
  ```bash
149
133
  harper deploy by_ref=true restart=true replicated=true
134
+ ```
135
+
136
+ Deploy a specific tag or commit with `ref`:
137
+
138
+ ```bash
150
139
  harper deploy ref=v1.2.0 restart=true replicated=true
151
140
  harper deploy ref=9f8c2a1 restart=true replicated=true
152
141
  ```
153
142
 
154
- - A `ref` is resolved to a full commit SHA before the deploy is sent, from the local checkout or the remote. A full commit SHA is accepted directly. If a `ref` can't be resolved, the deploy stops: run `git fetch` and retry, or pass a full SHA.
143
+ - Tags and branches are resolved to a full commit SHA before the deploy is sent. A `ref` that cannot be resolved stops the deploy — run `git fetch` and retry, or pass a full commit SHA.
155
144
  - Any other `ref` must name something a clone can fetch: `refs/heads/*` or `refs/tags/*`, or a bare branch or tag name. A qualified ref outside those, such as `refs/pull/123/head`, is rejected up front.
156
- - Commit and push first: the cluster clones from the remote. `by_ref` warns when the working tree is dirty, and when the commit isn't on any remote branch. The second check is skipped under GitHub Actions.
157
145
  - On a GitHub Actions `pull_request` run, `by_ref` deploys the pull request's head commit. If the event payload isn't readable, the deploy stops; pass the commit explicitly.
158
- - The cluster installs and builds from source on each node, so commit your lockfile if the build must be reproducible. If the build can't run on the node, deploy the built output as a payload instead.
146
+ - Commit and push first — the cluster clones from the remote and only sees pushed commits.
147
+
148
+ 8. **Check certification after a rolling deploy**: A deploy with `restart=rolling` certifies the release in a canary worker before rolling it out. The deploy response includes a `certification` field:
149
+
150
+ | `certification` | Meaning |
151
+ | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
152
+ | `certified` | The canary loaded the release; rollout proceeded. |
153
+ | `uncertified` | The rollout went on unchecked: the component ran nothing as it loaded (`loadComponent: dev-only`, an absent `if-installed` component, or safe mode), or no worker was replaced. |
154
+ | `unavailable` | Deploy restarted unchecked (no worker loads the component, `isolated` setting changed, already live, or `file:` directory source). |
155
+ | `not-requested` | The deploy did not restart. |
156
+ - **A rejected release fails the deploy.** If the canary throws while loading the component, exits, or doesn't report within a minute, the deploy fails with `400`. The release it replaced is made live again, and nothing is replicated to other nodes. The error carries the decision as an object in `certification` with `status` set to `rejected`, or to `interrupted` for a restart that stopped before the canary decided.
157
+ - **A release with nothing to go back to fails closed.** A rejected first deploy, or one whose previous release was not kept, stays on disk, but no worker on that node loads it, even after Harper restarts. `get_status` reports the component as failed and says why. Deploy a fix, or activate the same `deployment_id` again with `restart`.
158
+ - Another deploy or `drop_component` of the component on that node is refused with `409` until the rollout has finished.
159
159
 
160
- 8. **Deploy a private repository by reference**: Pass `credential=true` with `by_ref=true`. The CLI attaches a `credentials` reference, and the cluster resolves the secret in memory at clone time, so no token travels in the operation body or lands on disk.
160
+ 9. **Wait for a rolling deploy to finish**: A `deploy_component` with `"restart": "rolling"` returns a `restartJobId`. Poll it with `get_job` to learn whether every node took the release.
161
161
 
162
- ```bash
163
- harper deploy by_ref=true credential=true restart=true replicated=true
162
+ ```json
163
+ { "operation": "get_job", "id": "4a982782-929a-4507-8794-26dae1132def" }
164
164
  ```
165
165
 
166
- Provision that credential once per component and source with `harper deploy setup=true`. (With `provider=github-actions`, it sets up GitHub Actions deploys instead: see [deploying-from-ci.md](deploying-from-ci.md).) It is interactive, and its operations require **super_user**, so run it with an administrative credential, not the CI identity it provisions for. It:
167
- 1. Fetches the cluster's public key with `get_secrets_public_key`.
168
- 2. Encrypts the token locally into an `enc:v1:` envelope, so the plaintext never leaves your machine.
169
- 3. Stores only the ciphertext with `set_secret`, scoped to the component, never in the global `processEnv` tier.
170
- 4. Grants the component permission to resolve it with `grant_secret`.
171
- 5. Prints the `credentials` reference for the deploy to use.
172
-
173
- Use a **fine-grained** personal access token with **Contents: Read-only** on that one repository. Avoid the `gh` CLI's session token: it typically carries `repo`, `read:org`, `gist`, and `workflow` scopes across your whole account. The sealed token is durable, and later deploys reuse it.
166
+ `get_job` returns status `COMPLETE`, `IN_PROGRESS`, or `ERROR`. It answers only on the node that ran the job. A deploy-only role that waits for rolling deploys must include `get_job` in its operations allowlist.
167
+ - `list_deployments` returns records newest first. Filter by `project` and `status`; omit `limit` to return every matching record. A deploy in progress reads `pending`, or `loading`, until its `completed_at` is set.
174
168
 
175
169
  ## Examples
176
170
 
177
- **Deploy after logging in, and wait for a rolling restart:**
171
+ ### Full rolling deploy from a pinned tag
178
172
 
179
173
  ```bash
174
+ # Authenticate once
180
175
  harper login https://my-cluster.harperdbcloud.com
176
+
177
+ # Deploy a pinned release with rolling restart
181
178
  harper deploy \
182
179
  project=my-app \
183
- package="HarperFast/my-app" \
180
+ ref=v1.2.0 \
184
181
  target=https://my-cluster.harperdbcloud.com \
185
182
  restart=rolling \
186
- json=true > deploy.json
187
- # Poll the node that received the deploy until the job is COMPLETE or ERROR
188
- harper get_job id=<restartJobId from deploy.json> json=true
183
+ replicated=true
189
184
  ```
190
185
 
191
- **Roll back to the release a deploy replaced, node by node:**
186
+ ### Stage a build, then activate in a maintenance window
192
187
 
193
- ```bash
194
- harper list_deployments project=my-app status=success
195
- harper deploy project=my-app deployment_id=<previous deployment_id> restart=rolling json=true
196
- # Then poll its restartJobId with get_job, as above
188
+ ```json
189
+ {
190
+ "operation": "deploy_component",
191
+ "project": "my-app",
192
+ "package": "npm:@my-org/my-app@1.2.3",
193
+ "activate": false
194
+ }
197
195
  ```
198
196
 
199
- **Stage a release now, and make it live in a maintenance window:**
197
+ Response:
200
198
 
201
- ```bash
202
- harper deploy project=my-app package=npm:@my-org/my-app@1.2.3 activate=false
203
- # Later, with the deployment_id the stage returned
204
- harper deploy project=my-app deployment_id=<staged deployment_id> restart=rolling
199
+ ```json
200
+ {
201
+ "deployment_id": "a3f8c2d1-...",
202
+ "message": "Staged: my-app. Deploy it with deploy_component deployment_id=a3f8c2d1-..."
203
+ }
205
204
  ```
206
205
 
207
- **Deploy a pull request's head commit by reference in GitHub Actions:**
206
+ Activate later:
208
207
 
209
- ```bash
210
- harper deploy ref=${{ github.event.pull_request.head.sha }} restart=true replicated=true
208
+ ```json
209
+ {
210
+ "operation": "deploy_component",
211
+ "project": "my-app",
212
+ "deployment_id": "a3f8c2d1-...",
213
+ "restart": true
214
+ }
211
215
  ```
212
216
 
213
- **Deploy a private repository by reference:**
217
+ ### Roll back to a previous release
214
218
 
215
- ```bash
216
- # Once, as super_user
217
- harper deploy setup=true
219
+ ```json
220
+ {
221
+ "operation": "list_deployments",
222
+ "project": "my-app"
223
+ }
224
+ ```
225
+
226
+ Then:
218
227
 
219
- # Every deploy
220
- harper deploy by_ref=true credential=true restart=true replicated=true
228
+ ```json
229
+ {
230
+ "operation": "deploy_component",
231
+ "project": "my-app",
232
+ "deployment_id": "<id of the deployment you want back>",
233
+ "restart": true
234
+ }
221
235
  ```
236
+
237
+ ### Rejected canary — error response shape
238
+
239
+ ```json
240
+ {
241
+ "error": "my-app was not deployed: release 9b2e... failed to load in its canary worker: my-app.jsResource: ... Deployment a3f8c2d1..., the release it replaced, is live again. No other node received it. Deploy a fix, or activate deployment 9b2e... again once the cause is fixed.",
242
+ "deployment_id": "9b2e...",
243
+ "certification": {
244
+ "status": "rejected",
245
+ "reason": "my-app.jsResource: ...",
246
+ "failures": [
247
+ { "key": "my-app.jsResource", "name": "ResourceLoadError", "message": "...", "stack": "..." }
248
+ ],
249
+ "restored": "a3f8c2d1...",
250
+ "failed_closed": false
251
+ }
252
+ }
253
+ ```
254
+
255
+ ## Notes
256
+
257
+ - `harper login` stores a token; subsequent `harper deploy` calls to the same target need no credentials. See [creating-a-fabric-account-and-cluster.md](creating-a-fabric-account-and-cluster.md) for cluster setup.
258
+ - For GitHub Actions, prefer OIDC workload identity over stored tokens. See [deploying-from-ci.md](deploying-from-ci.md).
259
+ - `restart=rolling` and `activate=false` cannot be combined.
260
+ - `deployment_id` activation takes no `package`, `payload`, `credentials`, install options, `urlPath`, or `host` — supplying them is rejected.
261
+ - `file:` directory sources (`package: file:<dir>`) cannot be staged and are not kept as rollback targets.
262
+ - `stagingRetention.maxCount` (default `5`) caps staged builds and kept replaced releases together per component.
263
+ - `get_job` on a `restartJobId` answers only on the node that received the deploy; any other node returns an empty array.
264
+ - A rolling deploy's record reads `rolling_out` until the job has visited every node; filter `list_deployments` without `status` and check each record's `status` for a finished value (`success`, `partial`, `failed`, `staged`). `completed_at` alone does not confirm a finished state, since a `rolling_out` record already has it.
265
+ - `enc:v1:` envelopes store only ciphertext — plaintext never leaves your machine and never appears in operation logs or replication.
266
+ - Tags used in `refs/tags` are resolved to a commit SHA before the deploy is sent; a tag that moves mid-deploy cannot cause nodes to run different code.
267
+ - `super_user` is required to run `harper deploy setup=true`.
@@ -14,6 +14,8 @@ metadata:
14
14
 
15
15
  Instructions for the agent to follow when adding custom logic to automatically generated table resources in Harper.
16
16
 
17
+ **Instead of:** Middleware and controllers wrapped around CRUD routes. Use this rule rather than adding that service. See `harper-architecture`.
18
+
17
19
  ## When to Use
18
20
 
19
21
  Apply this rule when you need to override or augment the default HTTP handler behavior (GET, POST, PUT, PATCH, DELETE) for a Harper table resource. Use it when a table needs computed properties, input transformation, authorization checks, or custom error responses.
@@ -15,6 +15,8 @@ metadata:
15
15
 
16
16
  Instructions for the agent to follow when storing and serving binary data (images, audio, arbitrary content types) in Harper.
17
17
 
18
+ **Instead of:** S3 or GCS buckets for app-managed files. Use this rule rather than adding that service. See `harper-architecture`.
19
+
18
20
  ## When to Use
19
21
 
20
22
  Apply this rule when a Harper resource needs to accept, store, or serve binary payloads such as images, audio files, or calendar data. Use it when clients send raw binary via `PUT`/`POST`, or when they send `base64`-encoded data inside a JSON body.
@@ -15,6 +15,8 @@ metadata:
15
15
 
16
16
  Instructions for the agent to follow when loading environment variables from `.env` files into a Harper application using the `loadEnv` plugin.
17
17
 
18
+ **Instead of:** `dotenv`. Use this rule rather than adding that service. See `harper-architecture`.
19
+
18
20
  ## When to Use
19
21
 
20
22
  Apply this rule when a Harper application needs to supply secrets, API endpoints, or other configuration values to component code via `process.env` without hardcoding them. Use this whenever a `.env` file must be loaded at application startup.
@@ -16,6 +16,8 @@ metadata:
16
16
 
17
17
  Instructions for the agent to follow when implementing logging in Harper applications, including direct logger usage, tagged loggers, and console capture behavior.
18
18
 
19
+ **Instead of:** Separate log shippers for app logs (pino or winston transports). Use this rule rather than adding that service. See `harper-architecture`.
20
+
19
21
  ## When to Use
20
22
 
21
23
  Apply this rule when writing any JavaScript component, plugin, or resource that needs to emit structured log entries, filter logs by component, or capture existing `console.log` output into Harper's log system. Use it whenever you need to understand log levels, log entry format, or the `logger` global API.