@ai-slot/operations 0.1.0 → 0.1.2
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/README.md +32 -26
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,41 +1,47 @@
|
|
|
1
1
|
# @ai-slot/operations
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**English** | [简体中文](https://github.com/iannil/ai-slot-component/blob/master/packages/operations/README_zh-CN.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
An experimental public server-side package that provides version-state validation and a local single-writer file store. The 0.x API and persisted format do not yet guarantee compatibility across versions. Requires Node.js 22 or later. `openFileStore(directory)` maintains `state.json` and an exclusive `writer.lock` in the directory. Transactions commit drafts, approvals, publication records, pointers, and idempotency receipts as a single snapshot. The current limits are 64 MiB and 1,000 publication records. Only local filesystems with atomic rename semantics are supported; NFS, cloud-synced directories, and multiple service instances are not supported.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Installation
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
4. 用幂等键查询对应回执确认发布是否已经落盘,再决定后续业务动作。
|
|
9
|
+
```bash
|
|
10
|
+
npm install @ai-slot/operations
|
|
11
|
+
```
|
|
13
12
|
|
|
14
|
-
`
|
|
13
|
+
Import `openFileStore` and `createOperations`; the workflow is described below. A complete runnable reference service is available at [`examples/managed-slot`](https://github.com/iannil/ai-slot-component/tree/master/examples/managed-slot).
|
|
15
14
|
|
|
16
|
-
##
|
|
15
|
+
## Transactions and manual recovery
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
Transactions execute in call order, and reads enter the same queue. A commit first validates all references, then writes a temporary file in the same directory, syncs the file, renames it to `state.json`, and finally syncs the directory. A failure at `beforeRename` leaves the previous snapshot unchanged. A failure after rename returns `commit_unknown`, and the handle stops accepting further writes. Callers should check the idempotency receipt to determine the commit outcome, rather than treating this error as a definitive failure and retrying blindly.
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
1. Stop the sole service and back up the entire storage directory, including `state.json`, temporary files, and `writer.lock`.
|
|
20
|
+
2. Check the PID and random nonce in `writer.lock` and confirm that the original service process has exited. Do not automatically take over a lock based on its age.
|
|
21
|
+
3. Have an administrator manually move the leftover `writer.lock` out of the directory, then call `openFileStore` again. Startup checks the snapshot size before parsing and uses `assertState` to validate the structure, hashes, and all references. A corrupt snapshot prevents startup; it is never reset to an empty store.
|
|
22
|
+
4. Look up the corresponding receipt using the idempotency key to confirm whether the publication was persisted before deciding on the next business action.
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
2. `previewDraft(actor, draft.id)` 查看草稿、artifact 哈希和基线差异。
|
|
24
|
-
3. `approveDraft(actor, { draftId, artifactHash, expiresAt })` 批准该草稿。
|
|
25
|
-
4. `publishDraft(actor, { draftId, artifactHash, expectedRevision, idempotencyKey })` 原子发布,并取得新 revision 回执。
|
|
26
|
-
5. `deliver(slotId)` 公开交付当前版本;它不接受管理员身份,也不会返回草稿、批准人或来源凭据。
|
|
27
|
-
6. 需要回滚时,`prepareRollback(actor, { slotId, targetRevision, expectedRevision })` 将历史 artifact 建成新的回滚草稿。
|
|
28
|
-
7. 再次 `previewDraft` 和 `approveDraft`,审核这份回滚草稿。
|
|
29
|
-
8. `rollbackSlot(actor, { draftId, artifactHash, expectedRevision, idempotencyKey })` 发布新的 revision,而非移动指针回旧编号。
|
|
24
|
+
The `fault` injection option is for fault testing only, not application configuration.
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
## Drafts, publication, and public delivery
|
|
32
27
|
|
|
33
|
-
`
|
|
28
|
+
`createOperations(store, env)` is the unified entry point for governance and delivery. `listSlots(actor)` lists only slots with a policy for which the actor has `read` permission. `readSlot(actor, slotId)` returns only that slot's publication pointer and drafts. `previewDraft` and `getStatus` also require `read` permission for the slot. Draft creation validates the tree, source, and live baseline, then stores the content as an immutable artifact addressed by SHA-256. The preview's `previous` is pinned to the version at draft creation. Approval rechecks the hash, baseline, source, and component contract. Approval validity is limited to 15 minutes and must not extend beyond the source's expiry.
|
|
34
29
|
|
|
35
|
-
|
|
30
|
+
A complete workflow follows. Both publication and rollback require the approver to review the content hash and expiry again:
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
1. `createDraft(actor, { slotId, tree, baseRevision, sourceVersion })` creates a draft.
|
|
33
|
+
2. `previewDraft(actor, draft.id)` shows the draft, artifact hash, and differences from the baseline.
|
|
34
|
+
3. `approveDraft(actor, { draftId, artifactHash, expiresAt })` approves the draft.
|
|
35
|
+
4. `publishDraft(actor, { draftId, artifactHash, expectedRevision, idempotencyKey })` publishes atomically and returns a receipt for the new revision.
|
|
36
|
+
5. `deliver(slotId)` publicly delivers the current version. It accepts no administrator identity and returns no drafts, approver information, or source credentials.
|
|
37
|
+
6. To roll back, `prepareRollback(actor, { slotId, targetRevision, expectedRevision })` creates a new rollback draft from a historical artifact.
|
|
38
|
+
7. Run `previewDraft` and `approveDraft` again to review the rollback draft.
|
|
39
|
+
8. `rollbackSlot(actor, { draftId, artifactHash, expectedRevision, idempotencyKey })` publishes a new revision rather than moving the pointer back to an old revision number.
|
|
40
|
+
|
|
41
|
+
`deliver` returns version 1 JSON: `{ version, slot, tree, meta: { revision, artifactHash, sourceVersion, expiresAt } }`. `expiresAt` is the Unix timestamp in milliseconds stored in the artifact. All responses use `Cache-Control: no-store`. A known slot with no readable published content, or whose current source, component contract, or expiry fails validation, returns `503 { "error": "ai_unavailable" }`, allowing the page to retain its original content. Unknown slots return 404. Exceptions thrown while reading the source are normalized to `source_unavailable`; invalid source data still produces `source_invalid`. Public responses do not expose these internal details.
|
|
42
|
+
|
|
43
|
+
`getStatus(actor, slotId)` returns `{ desiredRevision, readableRevision, browserObservation }`. `desiredRevision` comes from the publication pointer and is retained even when the current source becomes invalid. `readableRevision` is populated only if the same live readability checks pass. `browserObservation` is always `null` because the server has no observation of browser rendering. Every delivery rereads the external source. An external source and a file transaction cannot be locked atomically across systems, so this package does not guarantee that the source remains unchanged after validation. This is a single-site reference implementation; it does not provide arbitrary factual or semantic verification, or automatic approval of financial promotions.
|
|
44
|
+
|
|
45
|
+
## Validation status and scope
|
|
40
46
|
|
|
41
|
-
|
|
47
|
+
This package does not start an HTTP service automatically or provide support for multiple instances or tenant isolation. Protocol and scripted validation have passed; validation with real operators and customer pilots has not yet been completed. Back up state before upgrading. Automatic migration of historical experimental snapshots is not guaranteed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-slot/operations",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@ai-slot/registry": "0.1.
|
|
15
|
+
"@ai-slot/registry": "0.1.3"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/node": "^22.0.0",
|