@authorbot/domain 0.1.24 → 0.1.26
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/CHANGELOG.md +32 -17
- package/dist/annotation-policy.d.ts +6 -6
- package/dist/annotation-policy.js +4 -4
- package/dist/annotation-state.d.ts +1 -1
- package/dist/annotation-state.js +1 -1
- package/dist/lease-token.d.ts +2 -2
- package/dist/lease-token.js +2 -2
- package/dist/lease.d.ts +4 -4
- package/dist/lease.js +4 -4
- package/dist/overrides.d.ts +1 -1
- package/dist/overrides.js +1 -1
- package/dist/submission.d.ts +1 -1
- package/dist/submission.js +2 -2
- package/dist/token.d.ts +1 -1
- package/dist/token.js +1 -1
- package/dist/vote.d.ts +4 -4
- package/dist/vote.js +4 -4
- package/dist/work-item-lifecycle.d.ts +1 -1
- package/dist/work-item-lifecycle.js +1 -1
- package/dist/work-item-state.d.ts +1 -1
- package/dist/work-item-state.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
What changed in each release, and why it mattered. Written for the person
|
|
4
|
-
deciding whether to upgrade, not for the person who wrote the commit
|
|
4
|
+
deciding whether to upgrade, not for the person who wrote the commit - so a
|
|
5
5
|
release that fixed something serious says what was broken and what it did to
|
|
6
6
|
you, rather than naming the function that changed.
|
|
7
7
|
|
|
@@ -9,10 +9,25 @@ Every published package shares this version. A tag builds, tests, and publishes
|
|
|
9
9
|
all of them together, so `@authorbot/cli@0.1.15` and `@authorbot/api@0.1.15` are
|
|
10
10
|
always the same commit.
|
|
11
11
|
|
|
12
|
+
## 0.1.26
|
|
13
|
+
|
|
14
|
+
- Removed every em-dash and en-dash from the tool's output, docs, and code. No
|
|
15
|
+
behaviour change; the wizard, error messages, and generated files now use
|
|
16
|
+
plain hyphens.
|
|
17
|
+
|
|
18
|
+
## 0.1.25
|
|
19
|
+
|
|
20
|
+
- **The collaborator skill.** `npx skills add JoeMattie/authorbot` installs a
|
|
21
|
+
skill that teaches an agent to contribute to an Authorbot book - the loop,
|
|
22
|
+
the safety rules, per-role guidance, and the full API reference - into Claude
|
|
23
|
+
Code and any other supported agent tooling. Also installable as a Claude Code
|
|
24
|
+
plugin (`/plugin marketplace add JoeMattie/authorbot`). The `agent` stage now
|
|
25
|
+
points at it.
|
|
26
|
+
|
|
12
27
|
## 0.1.24
|
|
13
28
|
|
|
14
29
|
- **`collaborate` commits and pushes what it writes.** It used to ask you to do
|
|
15
|
-
it "when you are ready"
|
|
30
|
+
it "when you are ready" - and until that push lands, the API cannot project
|
|
16
31
|
your book, so the settings page reports that it cannot read its own
|
|
17
32
|
configuration, with nothing connecting the two.
|
|
18
33
|
- **The agent stage stopped asking for a maintainer bearer token.** No author
|
|
@@ -20,7 +35,7 @@ always the same commit.
|
|
|
20
35
|
credential from elsewhere. `AUTHORBOT_API_TOKEN` still works for that case,
|
|
21
36
|
and everyone else is sent to the button on the settings page.
|
|
22
37
|
- Declining an optional step no longer tells you to run that step "to
|
|
23
|
-
continue", which made every optional thing look unfinished
|
|
38
|
+
continue", which made every optional thing look unfinished - `upgrade` most
|
|
24
39
|
of all, on a book far too new to need it.
|
|
25
40
|
|
|
26
41
|
## 0.1.23
|
|
@@ -35,7 +50,7 @@ always the same commit.
|
|
|
35
50
|
- **You can create an agent token from your book's settings.** Until now
|
|
36
51
|
nothing in Authorbot could make one: the API needs a maintainer session,
|
|
37
52
|
which only a browser holds, and the settings page could list and revoke
|
|
38
|
-
tokens but not create them
|
|
53
|
+
tokens but not create them - while the setup wizard asked for a bearer token
|
|
39
54
|
no author has ever been issued. The control sits under Agent tokens, shows
|
|
40
55
|
the value once, and defaults to the narrowest scopes an agent needs to read
|
|
41
56
|
chapters, claim work, and submit a draft.
|
|
@@ -44,7 +59,7 @@ always the same commit.
|
|
|
44
59
|
|
|
45
60
|
- **Installing the GitHub App no longer lands you on a 404.** GitHub was asked
|
|
46
61
|
to run its OAuth flow during installation, which redirected to a callback
|
|
47
|
-
that cannot exist yet
|
|
62
|
+
that cannot exist yet - the Worker's config needs the installation id that
|
|
48
63
|
installing is in the middle of producing. It now returns you to your book's
|
|
49
64
|
own site.
|
|
50
65
|
- **The agent stage stopped asking for a credential nobody has.** It wanted "a
|
|
@@ -59,8 +74,8 @@ always the same commit.
|
|
|
59
74
|
- **The GitHub App key was stored in a format the Worker cannot read.** GitHub's
|
|
60
75
|
manifest hands back a PKCS#1 key; WebCrypto, which is all a Cloudflare Worker
|
|
61
76
|
has, can only import PKCS#8. So every book reported its integration as
|
|
62
|
-
`invalid` and did no Git work at all
|
|
63
|
-
projection never ran, settings could not read `book.yml`
|
|
77
|
+
`invalid` and did no Git work at all - chapters could not be saved, the
|
|
78
|
+
projection never ran, settings could not read `book.yml` - with all three
|
|
64
79
|
credentials present and correct. **Books set up before this release need
|
|
65
80
|
their GitHub App deleted and `collaborate` run again**, because the key was
|
|
66
81
|
stored once and cannot be re-read.
|
|
@@ -72,7 +87,7 @@ always the same commit.
|
|
|
72
87
|
|
|
73
88
|
## 0.1.19
|
|
74
89
|
|
|
75
|
-
- Spinners with an elapsed timer on the steps that take minutes
|
|
90
|
+
- Spinners with an elapsed timer on the steps that take minutes - installing
|
|
76
91
|
the toolchain, waiting for a site to answer, checking the API. Silence for
|
|
77
92
|
four minutes reads as a hang.
|
|
78
93
|
- The mark is centred on the terminal's true width.
|
|
@@ -90,7 +105,7 @@ always the same commit.
|
|
|
90
105
|
- **`npm install` failed for everyone who started the documented way.** npx
|
|
91
106
|
exports its own configuration as `npm_config_*`, the wizard's `npm install`
|
|
92
107
|
inherited it, and resolved against npx's cache directory instead of your
|
|
93
|
-
book
|
|
108
|
+
book - so the install failed and you were left without a
|
|
94
109
|
`package-lock.json`, which both generated workflows refuse to run without. It
|
|
95
110
|
worked fine for anyone running the built binary directly, which is why it
|
|
96
111
|
looked like a problem with the machine.
|
|
@@ -104,10 +119,10 @@ always the same commit.
|
|
|
104
119
|
- **`unpublish` and `teardown`.** `npx @authorbot/create unpublish` removes the
|
|
105
120
|
Worker, the database and the GitHub App, leaving your repository and its
|
|
106
121
|
history alone so `publish` can put the site back. `teardown` also deletes the
|
|
107
|
-
remote repository, then tells you what to type to remove the local copy
|
|
122
|
+
remote repository, then tells you what to type to remove the local copy - it
|
|
108
123
|
never deletes files on your own disk.
|
|
109
124
|
- **The wizard is drawn rather than printed**: boxed stage headings, an arrow
|
|
110
|
-
for steps, and check/triangle/cross for outcomes
|
|
125
|
+
for steps, and check/triangle/cross for outcomes - each degrading to plain
|
|
111
126
|
ASCII under `NO_COLOR`, in a pipe, or on a dumb terminal.
|
|
112
127
|
- **A changelog**, here and inside every published package.
|
|
113
128
|
|
|
@@ -115,7 +130,7 @@ always the same commit.
|
|
|
115
130
|
|
|
116
131
|
- **The wizard can tell whether your book can actually save anything.** It used
|
|
117
132
|
to finish by checking that the API refused an anonymous caller, which a
|
|
118
|
-
completely unusable deployment does just as correctly as a healthy one
|
|
133
|
+
completely unusable deployment does just as correctly as a healthy one - see
|
|
119
134
|
0.1.14. New `GET /v1/health` reports whether the GitHub App is usable, and
|
|
120
135
|
`collaborate` refuses to switch a book's collaboration controls on when the
|
|
121
136
|
answer is no.
|
|
@@ -125,14 +140,14 @@ always the same commit.
|
|
|
125
140
|
- **Collaboration never worked on any book this wizard created.** The Worker
|
|
126
141
|
needs three GitHub App credentials and received two: the app id was read,
|
|
127
142
|
used to poll for the installation, and then dropped. With one missing it does
|
|
128
|
-
no Git work at all
|
|
143
|
+
no Git work at all - so chapters could not be saved, the projection never
|
|
129
144
|
ran, and settings could not read the book's own `book.yml`, while every
|
|
130
145
|
read-only page answered perfectly. If you set up a book before this release,
|
|
131
146
|
re-run `create-authorbot collaborate`.
|
|
132
147
|
- **You can sign out.** There was no way to. Two routes created a session and
|
|
133
148
|
none ended one, so a reader on a shared machine stayed signed in until the
|
|
134
149
|
cookie expired.
|
|
135
|
-
- **An account strip in the site header**
|
|
150
|
+
- **An account strip in the site header** - sign in, sign out, and the way into
|
|
136
151
|
Settings and the work queue. Previously a book with no chapters had no
|
|
137
152
|
sign-in anywhere, and `/settings/` and `/work/` were linked from nowhere.
|
|
138
153
|
- The API health check polls instead of judging on its first answer, which was
|
|
@@ -148,7 +163,7 @@ always the same commit.
|
|
|
148
163
|
|
|
149
164
|
- **A book with collaboration on showed no sign-in and no annotations.**
|
|
150
165
|
`book.yml` said annotations were public; the Worker was never told, so the
|
|
151
|
-
API refused every anonymous read
|
|
166
|
+
API refused every anonymous read - and the site gives up and renders nothing
|
|
152
167
|
when its first read fails, removing the very control that would have fixed
|
|
153
168
|
it.
|
|
154
169
|
|
|
@@ -185,7 +200,7 @@ always the same commit.
|
|
|
185
200
|
## 0.1.7
|
|
186
201
|
|
|
187
202
|
- **A successful deploy was reported as a failure** when the local resolver
|
|
188
|
-
still had the new hostname cached as non-existent
|
|
203
|
+
still had the new hostname cached as non-existent - which the wizard's own
|
|
189
204
|
domain check made near-certain.
|
|
190
205
|
- Every "run this to carry on" hint named `create-authorbot`, a binary `npx`
|
|
191
206
|
never installs.
|
|
@@ -203,7 +218,7 @@ always the same commit.
|
|
|
203
218
|
## 0.1.5
|
|
204
219
|
|
|
205
220
|
- Pointing the wizard at a directory that did not exist yet failed with a bare
|
|
206
|
-
ENOENT
|
|
221
|
+
ENOENT - including for the `directory: ./my-book` its own example config
|
|
207
222
|
prints.
|
|
208
223
|
- The pinned GitHub Actions moved off a deprecated line.
|
|
209
224
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Annotation policy (Phase 7 contract "Restricting")
|
|
2
|
+
* Annotation policy (Phase 7 contract "Restricting") - who may write to a
|
|
3
3
|
* book, and whether what they write appears immediately.
|
|
4
4
|
*
|
|
5
5
|
* | Mode | Who may write | Appears |
|
|
@@ -36,7 +36,7 @@ export type AnnotationPolicy = (typeof ANNOTATION_POLICIES)[number];
|
|
|
36
36
|
* The mode a book with no declared policy runs in: the Phase 2 behaviour,
|
|
37
37
|
* unchanged. A deployment upgrading into Phase 7 must not find its book
|
|
38
38
|
* suddenly writable by strangers, so the default is the restrictive end of the
|
|
39
|
-
* progression that people were already on
|
|
39
|
+
* progression that people were already on - not the permissive end, and not
|
|
40
40
|
* `locked` either, which would lock out the collaborators they already have.
|
|
41
41
|
*/
|
|
42
42
|
export declare const DEFAULT_ANNOTATION_POLICY: AnnotationPolicy;
|
|
@@ -52,21 +52,21 @@ export type AnnotationPolicyDenialReason =
|
|
|
52
52
|
| "locked"
|
|
53
53
|
/**
|
|
54
54
|
* Signed in and not a member, asking for something a non-member could never
|
|
55
|
-
* do (voting, claiming, submitting) even in an open book
|
|
55
|
+
* do (voting, claiming, submitting) even in an open book - those are member
|
|
56
56
|
* capabilities, and `open` widens commenting, not the work queue.
|
|
57
57
|
*/
|
|
58
58
|
| "member-capability";
|
|
59
59
|
/**
|
|
60
60
|
* The write capabilities the policy arbitrates.
|
|
61
61
|
*
|
|
62
|
-
* `annotate` is the one the policy table is actually about
|
|
62
|
+
* `annotate` is the one the policy table is actually about - commenting and
|
|
63
63
|
* suggesting. The other three are member capabilities that `open` and
|
|
64
64
|
* `approval-gated` do NOT widen to strangers: a book that welcomes comments
|
|
65
65
|
* from the internet is not thereby handing the internet its governance votes
|
|
66
66
|
* or its work queue.
|
|
67
67
|
*
|
|
68
68
|
* `locked` restricts all four, because "existing collaborators keep their
|
|
69
|
-
* membership and their history
|
|
69
|
+
* membership and their history - they simply cannot write until the policy
|
|
70
70
|
* opens again", and a vote that manufactures a work item is unambiguously a
|
|
71
71
|
* write.
|
|
72
72
|
*/
|
|
@@ -83,7 +83,7 @@ export interface AnnotationPolicyRequest {
|
|
|
83
83
|
* Decide whether the policy admits this write.
|
|
84
84
|
*
|
|
85
85
|
* This answers the policy question ONLY. Scope checks, freeze, the agent pause,
|
|
86
|
-
* and rate limits are separate gates applied alongside it
|
|
86
|
+
* and rate limits are separate gates applied alongside it - a request must
|
|
87
87
|
* satisfy all of them, and each refuses with its own problem type so the caller
|
|
88
88
|
* can tell "the book is locked" from "the book is frozen" from "you are going
|
|
89
89
|
* too fast".
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Annotation policy (Phase 7 contract "Restricting")
|
|
2
|
+
* Annotation policy (Phase 7 contract "Restricting") - who may write to a
|
|
3
3
|
* book, and whether what they write appears immediately.
|
|
4
4
|
*
|
|
5
5
|
* | Mode | Who may write | Appears |
|
|
@@ -39,7 +39,7 @@ export const ANNOTATION_POLICIES = [
|
|
|
39
39
|
* The mode a book with no declared policy runs in: the Phase 2 behaviour,
|
|
40
40
|
* unchanged. A deployment upgrading into Phase 7 must not find its book
|
|
41
41
|
* suddenly writable by strangers, so the default is the restrictive end of the
|
|
42
|
-
* progression that people were already on
|
|
42
|
+
* progression that people were already on - not the permissive end, and not
|
|
43
43
|
* `locked` either, which would lock out the collaborators they already have.
|
|
44
44
|
*/
|
|
45
45
|
export const DEFAULT_ANNOTATION_POLICY = "collaborators-only";
|
|
@@ -54,7 +54,7 @@ export function policyRequiresApproval(policy) {
|
|
|
54
54
|
* Decide whether the policy admits this write.
|
|
55
55
|
*
|
|
56
56
|
* This answers the policy question ONLY. Scope checks, freeze, the agent pause,
|
|
57
|
-
* and rate limits are separate gates applied alongside it
|
|
57
|
+
* and rate limits are separate gates applied alongside it - a request must
|
|
58
58
|
* satisfy all of them, and each refuses with its own problem type so the caller
|
|
59
59
|
* can tell "the book is locked" from "the book is frozen" from "you are going
|
|
60
60
|
* too fast".
|
|
@@ -89,7 +89,7 @@ export function checkAnnotationPolicy(request) {
|
|
|
89
89
|
}
|
|
90
90
|
return ALLOWED;
|
|
91
91
|
}
|
|
92
|
-
// collaborators-only
|
|
92
|
+
// collaborators-only - the Phase 2 behaviour, and the default.
|
|
93
93
|
if (isMember) {
|
|
94
94
|
return ALLOWED;
|
|
95
95
|
}
|
|
@@ -8,7 +8,7 @@ export type { AnnotationStatus };
|
|
|
8
8
|
* section 4). `open` fans out; `rejected -> open` is the Phase 3 maintainer
|
|
9
9
|
* reopen override (Phase 3 contract section 4); every other status is
|
|
10
10
|
* terminal. The reanchor flow (`needs_reanchor -> open`) is intentionally not
|
|
11
|
-
* legal yet
|
|
11
|
+
* legal yet - adding transitions later is additive.
|
|
12
12
|
*/
|
|
13
13
|
export declare const ANNOTATION_TRANSITIONS: Readonly<Record<AnnotationStatus, readonly AnnotationStatus[]>>;
|
|
14
14
|
export declare function canTransitionAnnotation(from: AnnotationStatus, to: AnnotationStatus): boolean;
|
package/dist/annotation-state.js
CHANGED
|
@@ -6,7 +6,7 @@ export { ANNOTATION_STATUSES };
|
|
|
6
6
|
* section 4). `open` fans out; `rejected -> open` is the Phase 3 maintainer
|
|
7
7
|
* reopen override (Phase 3 contract section 4); every other status is
|
|
8
8
|
* terminal. The reanchor flow (`needs_reanchor -> open`) is intentionally not
|
|
9
|
-
* legal yet
|
|
9
|
+
* legal yet - adding transitions later is additive.
|
|
10
10
|
*/
|
|
11
11
|
export const ANNOTATION_TRANSITIONS = Object.freeze({
|
|
12
12
|
open: [
|
package/dist/lease-token.d.ts
CHANGED
|
@@ -3,11 +3,11 @@ import { z } from "zod";
|
|
|
3
3
|
* Lease-token FORMAT helpers only (Phase 4 contract section 2): parse and
|
|
4
4
|
* shape-check, no crypto. Generating the 256-bit random secret, hashing it
|
|
5
5
|
* (SHA-256), storing only the hash, and the constant-time compare are the
|
|
6
|
-
* API layer's job
|
|
6
|
+
* API layer's job - exactly the split used for agent tokens in `token.ts`.
|
|
7
7
|
* Failure results carry a reason only and never echo any part of the value;
|
|
8
8
|
* lease tokens are never logged.
|
|
9
9
|
*
|
|
10
|
-
* Format (resolved ambiguity
|
|
10
|
+
* Format (resolved ambiguity - the contracts pin "opaque 256-bit token" but
|
|
11
11
|
* no encoding): `authorbot_lease_` + 43 base64url chars, matching the agent
|
|
12
12
|
* token secret encoding. The distinct prefix makes a leaked lease token
|
|
13
13
|
* identifiable and unconfusable with an agent credential (an agent token is
|
package/dist/lease-token.js
CHANGED
|
@@ -3,11 +3,11 @@ import { z } from "zod";
|
|
|
3
3
|
* Lease-token FORMAT helpers only (Phase 4 contract section 2): parse and
|
|
4
4
|
* shape-check, no crypto. Generating the 256-bit random secret, hashing it
|
|
5
5
|
* (SHA-256), storing only the hash, and the constant-time compare are the
|
|
6
|
-
* API layer's job
|
|
6
|
+
* API layer's job - exactly the split used for agent tokens in `token.ts`.
|
|
7
7
|
* Failure results carry a reason only and never echo any part of the value;
|
|
8
8
|
* lease tokens are never logged.
|
|
9
9
|
*
|
|
10
|
-
* Format (resolved ambiguity
|
|
10
|
+
* Format (resolved ambiguity - the contracts pin "opaque 256-bit token" but
|
|
11
11
|
* no encoding): `authorbot_lease_` + 43 base64url chars, matching the agent
|
|
12
12
|
* token secret encoding. The distinct prefix makes a leaked lease token
|
|
13
13
|
* identifiable and unconfusable with an agent credential (an agent token is
|
package/dist/lease.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type IsoDurationParseResult = {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Parse the ISO-8601 duration subset the contracts use (`PT30M`, `PT4H`,
|
|
21
|
-
* `P1D`, combinations with integer designators; no years/months/weeks
|
|
21
|
+
* `P1D`, combinations with integer designators; no years/months/weeks -
|
|
22
22
|
* calendar units are ambiguous in milliseconds). Used to validate `LEASE_*`
|
|
23
23
|
* env overrides at boot (Phase 4 contract section 2).
|
|
24
24
|
*/
|
|
@@ -66,7 +66,7 @@ export type LeaseInactiveReason = "expired" | "released" | "revoked";
|
|
|
66
66
|
* Whether a lease still backs commands at `now`. Check order follows the
|
|
67
67
|
* contract section 4 verification order ("not expired / not released"):
|
|
68
68
|
* expired first, then released, then revoked. Used by renew, release, and
|
|
69
|
-
* submission checks alike
|
|
69
|
+
* submission checks alike - an expired, released, or revoked lease can do
|
|
70
70
|
* nothing further (contract section 2: renewing an expired lease is a 409).
|
|
71
71
|
*/
|
|
72
72
|
export declare function checkLeaseActive(lease: LeaseSnapshot, now: Date): Decision<LeaseInactiveReason>;
|
|
@@ -93,7 +93,7 @@ export type ClaimCheckResult = {
|
|
|
93
93
|
* "none" is unambiguous). That combination is what an interrupted expiry or a
|
|
94
94
|
* bare administrative revocation leaves behind, and treating it as
|
|
95
95
|
* `lease-held` made such items permanently unclaimable, unreleasable, and
|
|
96
|
-
* unsweepable
|
|
96
|
+
* unsweepable - recoverable only by direct database surgery. Claiming
|
|
97
97
|
* self-heals it instead: `priorLeaseExpired` sends the caller down the
|
|
98
98
|
* expire-then-claim path, whose compare-and-swap starts from `leased`.
|
|
99
99
|
*/
|
|
@@ -108,7 +108,7 @@ export type RenewCheckResult = {
|
|
|
108
108
|
* renews; the new expiry is the current `expires_at` plus the renewal
|
|
109
109
|
* duration ("extends by"), clamped to `max_expires_at`. When the lease
|
|
110
110
|
* already sits at its max-total cap so no extension is possible, the renewal
|
|
111
|
-
* is rejected with `max-total-exceeded` rather than succeeding as a no-op
|
|
111
|
+
* is rejected with `max-total-exceeded` rather than succeeding as a no-op -
|
|
112
112
|
* a partially clamped extension is still allowed. Verifying the presented
|
|
113
113
|
* token against the stored hash happens before this in the API layer.
|
|
114
114
|
*/
|
package/dist/lease.js
CHANGED
|
@@ -26,7 +26,7 @@ export const LEASE_RENEWAL_PROMPT_BEFORE_MS = 5 * MS_PER_MINUTE;
|
|
|
26
26
|
const ISO_DURATION_REGEX = /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/;
|
|
27
27
|
/**
|
|
28
28
|
* Parse the ISO-8601 duration subset the contracts use (`PT30M`, `PT4H`,
|
|
29
|
-
* `P1D`, combinations with integer designators; no years/months/weeks
|
|
29
|
+
* `P1D`, combinations with integer designators; no years/months/weeks -
|
|
30
30
|
* calendar units are ambiguous in milliseconds). Used to validate `LEASE_*`
|
|
31
31
|
* env overrides at boot (Phase 4 contract section 2).
|
|
32
32
|
*/
|
|
@@ -97,7 +97,7 @@ export function isLeaseExpired(lease, now) {
|
|
|
97
97
|
* Whether a lease still backs commands at `now`. Check order follows the
|
|
98
98
|
* contract section 4 verification order ("not expired / not released"):
|
|
99
99
|
* expired first, then released, then revoked. Used by renew, release, and
|
|
100
|
-
* submission checks alike
|
|
100
|
+
* submission checks alike - an expired, released, or revoked lease can do
|
|
101
101
|
* nothing further (contract section 2: renewing an expired lease is a 409).
|
|
102
102
|
*/
|
|
103
103
|
export function checkLeaseActive(lease, now) {
|
|
@@ -125,7 +125,7 @@ export function checkLeaseActive(lease, now) {
|
|
|
125
125
|
* "none" is unambiguous). That combination is what an interrupted expiry or a
|
|
126
126
|
* bare administrative revocation leaves behind, and treating it as
|
|
127
127
|
* `lease-held` made such items permanently unclaimable, unreleasable, and
|
|
128
|
-
* unsweepable
|
|
128
|
+
* unsweepable - recoverable only by direct database surgery. Claiming
|
|
129
129
|
* self-heals it instead: `priorLeaseExpired` sends the caller down the
|
|
130
130
|
* expire-then-claim path, whose compare-and-swap starts from `leased`.
|
|
131
131
|
*/
|
|
@@ -146,7 +146,7 @@ export function checkWorkItemClaimable(status, activeLease, now) {
|
|
|
146
146
|
* renews; the new expiry is the current `expires_at` plus the renewal
|
|
147
147
|
* duration ("extends by"), clamped to `max_expires_at`. When the lease
|
|
148
148
|
* already sits at its max-total cap so no extension is possible, the renewal
|
|
149
|
-
* is rejected with `max-total-exceeded` rather than succeeding as a no-op
|
|
149
|
+
* is rejected with `max-total-exceeded` rather than succeeding as a no-op -
|
|
150
150
|
* a partially clamped extension is still allowed. Verifying the presented
|
|
151
151
|
* token against the stored hash happens before this in the API layer.
|
|
152
152
|
*/
|
package/dist/overrides.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export declare const reopenSuggestionCommandSchema: z.ZodObject<{
|
|
|
36
36
|
export type ReopenSuggestionCommand = z.infer<typeof reopenSuggestionCommandSchema>;
|
|
37
37
|
/**
|
|
38
38
|
* Override 4: force-create a work item bypassing the rule. `work_type` is not
|
|
39
|
-
* part of the command
|
|
39
|
+
* part of the command - it resolves from the annotation scope exactly as
|
|
40
40
|
* rule-created items do (Phase 3 contract section 3).
|
|
41
41
|
*/
|
|
42
42
|
export declare const forceCreateWorkItemCommandSchema: z.ZodObject<{
|
package/dist/overrides.js
CHANGED
|
@@ -38,7 +38,7 @@ export const reopenSuggestionCommandSchema = z.strictObject({
|
|
|
38
38
|
});
|
|
39
39
|
/**
|
|
40
40
|
* Override 4: force-create a work item bypassing the rule. `work_type` is not
|
|
41
|
-
* part of the command
|
|
41
|
+
* part of the command - it resolves from the annotation scope exactly as
|
|
42
42
|
* rule-created items do (Phase 3 contract section 3).
|
|
43
43
|
*/
|
|
44
44
|
export const forceCreateWorkItemCommandSchema = z.strictObject({
|
package/dist/submission.d.ts
CHANGED
|
@@ -75,7 +75,7 @@ export type SubmissionBaseDenialReason = "base-revision-mismatch" | "base-hash-m
|
|
|
75
75
|
* (contract section 4). Revision is checked before hash so the commoner
|
|
76
76
|
* staleness cause surfaces first. Hash comparison here is not secret
|
|
77
77
|
* material (both values are content hashes the client already holds), so a
|
|
78
|
-
* plain compare is correct
|
|
78
|
+
* plain compare is correct - constant-time treatment is for lease tokens.
|
|
79
79
|
*/
|
|
80
80
|
export declare function checkSubmissionBase(bundle: {
|
|
81
81
|
readonly baseRevision: number;
|
package/dist/submission.js
CHANGED
|
@@ -70,7 +70,7 @@ export const contentHashSchema = z
|
|
|
70
70
|
.regex(CONTENT_HASH_REGEX, "must be 'sha256:' followed by 64 lowercase hex characters");
|
|
71
71
|
/**
|
|
72
72
|
* Replacement content: CRLF folded to LF (matching chapter storage) but NOT
|
|
73
|
-
* trimmed
|
|
73
|
+
* trimmed - leading/trailing whitespace is meaningful in a range
|
|
74
74
|
* replacement. Emptiness is a per-type rule handled in the command schema:
|
|
75
75
|
* an empty `range_replacement` is a deletion and legal; block and chapter
|
|
76
76
|
* replacements must be non-empty.
|
|
@@ -118,7 +118,7 @@ export const submitWorkCommandSchema = z
|
|
|
118
118
|
* (contract section 4). Revision is checked before hash so the commoner
|
|
119
119
|
* staleness cause surfaces first. Hash comparison here is not secret
|
|
120
120
|
* material (both values are content hashes the client already holds), so a
|
|
121
|
-
* plain compare is correct
|
|
121
|
+
* plain compare is correct - constant-time treatment is for lease tokens.
|
|
122
122
|
*/
|
|
123
123
|
export function checkSubmissionBase(bundle, submission) {
|
|
124
124
|
if (submission.baseRevision !== bundle.baseRevision) {
|
package/dist/token.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export type AgentTokenParseResult = {
|
|
|
22
22
|
};
|
|
23
23
|
/**
|
|
24
24
|
* Shape-check a presented credential and split off the secret part (which the
|
|
25
|
-
* API layer hashes for lookup). Failure results carry a reason only
|
|
25
|
+
* API layer hashes for lookup). Failure results carry a reason only - never
|
|
26
26
|
* any fragment of the presented value.
|
|
27
27
|
*/
|
|
28
28
|
export declare function parseAgentToken(value: string): AgentTokenParseResult;
|
package/dist/token.js
CHANGED
|
@@ -19,7 +19,7 @@ export function isAgentTokenFormat(value) {
|
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Shape-check a presented credential and split off the secret part (which the
|
|
22
|
-
* API layer hashes for lookup). Failure results carry a reason only
|
|
22
|
+
* API layer hashes for lookup). Failure results carry a reason only - never
|
|
23
23
|
* any fragment of the presented value.
|
|
24
24
|
*/
|
|
25
25
|
export function parseAgentToken(value) {
|
package/dist/vote.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const voteValueSchema: z.ZodEnum<{
|
|
|
15
15
|
abstain: "abstain";
|
|
16
16
|
}>;
|
|
17
17
|
export type VoteValue = z.infer<typeof voteValueSchema>;
|
|
18
|
-
/** `PUT .../annotations/{annotationId}/vote`
|
|
18
|
+
/** `PUT .../annotations/{annotationId}/vote` - route param + body merged. */
|
|
19
19
|
export declare const castVoteCommandSchema: z.ZodObject<{
|
|
20
20
|
annotationId: z.ZodString;
|
|
21
21
|
value: z.ZodEnum<{
|
|
@@ -25,7 +25,7 @@ export declare const castVoteCommandSchema: z.ZodObject<{
|
|
|
25
25
|
}>;
|
|
26
26
|
}, z.core.$strict>;
|
|
27
27
|
export type CastVoteCommand = z.infer<typeof castVoteCommandSchema>;
|
|
28
|
-
/** `DELETE .../annotations/{annotationId}/vote`
|
|
28
|
+
/** `DELETE .../annotations/{annotationId}/vote` - the command is the route param. */
|
|
29
29
|
export declare const clearVoteCommandSchema: z.ZodObject<{
|
|
30
30
|
annotationId: z.ZodString;
|
|
31
31
|
}, z.core.$strict>;
|
|
@@ -33,8 +33,8 @@ export type ClearVoteCommand = z.infer<typeof clearVoteCommandSchema>;
|
|
|
33
33
|
export type VoteDenialReason = "not-a-suggestion";
|
|
34
34
|
/**
|
|
35
35
|
* Suggestion-only guard (contract section 2: votes on comments → 422). Votes
|
|
36
|
-
* stay legal after `open`
|
|
37
|
-
* `work_item_created` annotations (contract section 4)
|
|
36
|
+
* stay legal after `open` - sticky decisions require tracking vote changes on
|
|
37
|
+
* `work_item_created` annotations (contract section 4) - so annotation status
|
|
38
38
|
* is deliberately not checked here; `votes:write` scope enforcement is the
|
|
39
39
|
* API layer's (`requireScope`).
|
|
40
40
|
*/
|
package/dist/vote.js
CHANGED
|
@@ -10,19 +10,19 @@ import { ALLOWED, denied } from "./decision.js";
|
|
|
10
10
|
/** Vote values (contract section 2; mirrors `authorbot.instance/v1` `votes.values`). */
|
|
11
11
|
export const VOTE_VALUES = ["approve", "reject", "abstain"];
|
|
12
12
|
export const voteValueSchema = z.enum(VOTE_VALUES);
|
|
13
|
-
/** `PUT .../annotations/{annotationId}/vote`
|
|
13
|
+
/** `PUT .../annotations/{annotationId}/vote` - route param + body merged. */
|
|
14
14
|
export const castVoteCommandSchema = z.strictObject({
|
|
15
15
|
annotationId: uuidv7Schema,
|
|
16
16
|
value: voteValueSchema,
|
|
17
17
|
});
|
|
18
|
-
/** `DELETE .../annotations/{annotationId}/vote`
|
|
18
|
+
/** `DELETE .../annotations/{annotationId}/vote` - the command is the route param. */
|
|
19
19
|
export const clearVoteCommandSchema = z.strictObject({
|
|
20
20
|
annotationId: uuidv7Schema,
|
|
21
21
|
});
|
|
22
22
|
/**
|
|
23
23
|
* Suggestion-only guard (contract section 2: votes on comments → 422). Votes
|
|
24
|
-
* stay legal after `open`
|
|
25
|
-
* `work_item_created` annotations (contract section 4)
|
|
24
|
+
* stay legal after `open` - sticky decisions require tracking vote changes on
|
|
25
|
+
* `work_item_created` annotations (contract section 4) - so annotation status
|
|
26
26
|
* is deliberately not checked here; `votes:write` scope enforcement is the
|
|
27
27
|
* API layer's (`requireScope`).
|
|
28
28
|
*/
|
|
@@ -5,7 +5,7 @@ import { type Decision, type Denied } from "./decision.js";
|
|
|
5
5
|
* Phase 3 gate lifted (Phase 4 contract sections 2, 4, 5). The graph itself
|
|
6
6
|
* has been declared since Phase 3 (`WORK_ITEM_TRANSITIONS`); this module
|
|
7
7
|
* adds the executable, trigger-labelled form. `transitionWorkItem` (the
|
|
8
|
-
* Phase 3-gated function) is left untouched for compatibility
|
|
8
|
+
* Phase 3-gated function) is left untouched for compatibility - Phase 4
|
|
9
9
|
* call sites use `transitionWorkItemPhase4` / `applyWorkItemTrigger`.
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
@@ -6,7 +6,7 @@ import { WORK_ITEM_TRANSITIONS, canTransitionWorkItem } from "./work-item-state.
|
|
|
6
6
|
* Phase 3 gate lifted (Phase 4 contract sections 2, 4, 5). The graph itself
|
|
7
7
|
* has been declared since Phase 3 (`WORK_ITEM_TRANSITIONS`); this module
|
|
8
8
|
* adds the executable, trigger-labelled form. `transitionWorkItem` (the
|
|
9
|
-
* Phase 3-gated function) is left untouched for compatibility
|
|
9
|
+
* Phase 3-gated function) is left untouched for compatibility - Phase 4
|
|
10
10
|
* call sites use `transitionWorkItemPhase4` / `applyWorkItemTrigger`.
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
@@ -5,7 +5,7 @@ export type { WorkItemStatus };
|
|
|
5
5
|
/**
|
|
6
6
|
* Work-item state machine (design section 9.5). The full transition graph is
|
|
7
7
|
* declared so Phase 4 is additive data, but Phase 3 stops at `ready` (Phase 3
|
|
8
|
-
* contract section 1: claims/leases/submissions are out of scope)
|
|
8
|
+
* contract section 1: claims/leases/submissions are out of scope) - the only
|
|
9
9
|
* transition that may actually execute is `ready -> cancelled` (maintainer
|
|
10
10
|
* cancel). Every other graph edge is phase-gated: legal in the design, denied
|
|
11
11
|
* at runtime with `phase-not-enabled` until Phase 4 lifts the gate.
|
package/dist/work-item-state.js
CHANGED
|
@@ -4,7 +4,7 @@ export { WORK_ITEM_STATUSES };
|
|
|
4
4
|
/**
|
|
5
5
|
* Work-item state machine (design section 9.5). The full transition graph is
|
|
6
6
|
* declared so Phase 4 is additive data, but Phase 3 stops at `ready` (Phase 3
|
|
7
|
-
* contract section 1: claims/leases/submissions are out of scope)
|
|
7
|
+
* contract section 1: claims/leases/submissions are out of scope) - the only
|
|
8
8
|
* transition that may actually execute is `ready -> cancelled` (maintainer
|
|
9
9
|
* cancel). Every other graph edge is phase-gated: legal in the design, denied
|
|
10
10
|
* at runtime with `phase-not-enabled` until Phase 4 lifts the gate.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@authorbot/domain",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.26",
|
|
4
4
|
"description": "Pure domain logic for Authorbot: role/scope authorization, annotation and Git-operation state machines, command validators, and token/session value rules (Phase 2 contract section 3)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"authorbot",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"zod": "^4.0.0",
|
|
43
|
-
"@authorbot/schemas": "0.1.
|
|
43
|
+
"@authorbot/schemas": "0.1.26"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^22.0.0",
|