@authorbot/schemas 0.1.0

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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/dist/annotation.d.ts +172 -0
  3. package/dist/annotation.js +96 -0
  4. package/dist/attribution.d.ts +25 -0
  5. package/dist/attribution.js +19 -0
  6. package/dist/book.d.ts +104 -0
  7. package/dist/book.js +105 -0
  8. package/dist/build.d.ts +44 -0
  9. package/dist/build.js +28 -0
  10. package/dist/chapter.d.ts +37 -0
  11. package/dist/chapter.js +29 -0
  12. package/dist/character.d.ts +15 -0
  13. package/dist/character.js +16 -0
  14. package/dist/decision.d.ts +34 -0
  15. package/dist/decision.js +31 -0
  16. package/dist/index.d.ts +29 -0
  17. package/dist/index.js +15 -0
  18. package/dist/instance.d.ts +260 -0
  19. package/dist/instance.js +101 -0
  20. package/dist/json-schemas.d.ts +455 -0
  21. package/dist/json-schemas.js +61 -0
  22. package/dist/primitives.d.ts +58 -0
  23. package/dist/primitives.js +101 -0
  24. package/dist/release.d.ts +17 -0
  25. package/dist/release.js +19 -0
  26. package/dist/scripts/generate-json-schemas.d.ts +2 -0
  27. package/dist/scripts/generate-json-schemas.js +14 -0
  28. package/dist/story-graph.d.ts +132 -0
  29. package/dist/story-graph.js +56 -0
  30. package/dist/timeline.d.ts +35 -0
  31. package/dist/timeline.js +28 -0
  32. package/dist/work-item.d.ts +75 -0
  33. package/dist/work-item.js +48 -0
  34. package/json/annotation.schema.json +279 -0
  35. package/json/attribution.schema.json +52 -0
  36. package/json/book.schema.json +270 -0
  37. package/json/build.schema.json +84 -0
  38. package/json/chapter.schema.json +89 -0
  39. package/json/character.schema.json +39 -0
  40. package/json/decision.schema.json +69 -0
  41. package/json/instance.schema.json +273 -0
  42. package/json/release.schema.json +52 -0
  43. package/json/reply.schema.json +43 -0
  44. package/json/story-graph.schema.json +159 -0
  45. package/json/timeline.schema.json +91 -0
  46. package/json/work-item.schema.json +78 -0
  47. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joe Mattie
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,172 @@
1
+ import { z } from "zod";
2
+ /** Annotation lifecycle states (contract section 4, design section 9.4). */
3
+ export declare const ANNOTATION_STATUSES: readonly ["open", "work_item_created", "accepted", "resolved", "rejected", "withdrawn", "superseded", "orphaned", "needs_reanchor"];
4
+ export declare const annotationStatusSchema: z.ZodEnum<{
5
+ open: "open";
6
+ work_item_created: "work_item_created";
7
+ accepted: "accepted";
8
+ resolved: "resolved";
9
+ rejected: "rejected";
10
+ withdrawn: "withdrawn";
11
+ superseded: "superseded";
12
+ orphaned: "orphaned";
13
+ needs_reanchor: "needs_reanchor";
14
+ }>;
15
+ export type AnnotationStatus = z.infer<typeof annotationStatusSchema>;
16
+ export declare const ANNOTATION_KINDS: readonly ["comment", "suggestion"];
17
+ export declare const annotationKindSchema: z.ZodEnum<{
18
+ comment: "comment";
19
+ suggestion: "suggestion";
20
+ }>;
21
+ export type AnnotationKind = z.infer<typeof annotationKindSchema>;
22
+ /**
23
+ * Range target selector (design section 10.1). Selector field names are
24
+ * camelCase exactly as in the design payload: `blockId`, `textPosition`,
25
+ * `textQuote`. Positions are offsets into the normalized plain-text stream of
26
+ * the block, not raw HTML offsets.
27
+ */
28
+ export declare const textPositionSchema: z.ZodObject<{
29
+ start: z.ZodNumber;
30
+ end: z.ZodNumber;
31
+ }, z.core.$strict>;
32
+ export type TextPosition = z.infer<typeof textPositionSchema>;
33
+ /** Contract 2b §2.2: quote context is at most 32 characters each side. */
34
+ export declare const MAX_QUOTE_CONTEXT = 32;
35
+ /**
36
+ * Server-side ceiling for `textQuote.exact` (a selection within a single
37
+ * semantic block, so far below the 32 KiB body limit). Enforced here so an
38
+ * attacker-chosen selector can never smuggle megabytes into the annotations
39
+ * row and the committed `.authorbot/annotations/<id>/annotation.md` artifact.
40
+ */
41
+ export declare const MAX_QUOTE_EXACT: number;
42
+ export declare const textQuoteSchema: z.ZodObject<{
43
+ exact: z.ZodString;
44
+ prefix: z.ZodOptional<z.ZodString>;
45
+ suffix: z.ZodOptional<z.ZodString>;
46
+ }, z.core.$strict>;
47
+ export type TextQuote = z.infer<typeof textQuoteSchema>;
48
+ export declare const rangeTargetSchema: z.ZodObject<{
49
+ blockId: z.ZodString;
50
+ textPosition: z.ZodObject<{
51
+ start: z.ZodNumber;
52
+ end: z.ZodNumber;
53
+ }, z.core.$strict>;
54
+ textQuote: z.ZodObject<{
55
+ exact: z.ZodString;
56
+ prefix: z.ZodOptional<z.ZodString>;
57
+ suffix: z.ZodOptional<z.ZodString>;
58
+ }, z.core.$strict>;
59
+ }, z.core.$strict>;
60
+ export type RangeTarget = z.infer<typeof rangeTargetSchema>;
61
+ export declare const blockTargetSchema: z.ZodObject<{
62
+ blockId: z.ZodString;
63
+ }, z.core.$strict>;
64
+ export type BlockTarget = z.infer<typeof blockTargetSchema>;
65
+ /**
66
+ * Annotation frontmatter `.authorbot/annotations/<id>/annotation.md` —
67
+ * `authorbot.annotation/v1` (contract section 4). `target` is required for
68
+ * `range` and `block` scopes and forbidden for `chapter` scope.
69
+ */
70
+ export declare const annotationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
71
+ scope: z.ZodLiteral<"range">;
72
+ target: z.ZodObject<{
73
+ blockId: z.ZodString;
74
+ textPosition: z.ZodObject<{
75
+ start: z.ZodNumber;
76
+ end: z.ZodNumber;
77
+ }, z.core.$strict>;
78
+ textQuote: z.ZodObject<{
79
+ exact: z.ZodString;
80
+ prefix: z.ZodOptional<z.ZodString>;
81
+ suffix: z.ZodOptional<z.ZodString>;
82
+ }, z.core.$strict>;
83
+ }, z.core.$strict>;
84
+ schema: z.ZodLiteral<"authorbot.annotation/v1">;
85
+ id: z.ZodString;
86
+ kind: z.ZodEnum<{
87
+ comment: "comment";
88
+ suggestion: "suggestion";
89
+ }>;
90
+ chapter_id: z.ZodString;
91
+ chapter_revision: z.ZodNumber;
92
+ author: z.ZodString;
93
+ status: z.ZodEnum<{
94
+ open: "open";
95
+ work_item_created: "work_item_created";
96
+ accepted: "accepted";
97
+ resolved: "resolved";
98
+ rejected: "rejected";
99
+ withdrawn: "withdrawn";
100
+ superseded: "superseded";
101
+ orphaned: "orphaned";
102
+ needs_reanchor: "needs_reanchor";
103
+ }>;
104
+ created_at: z.ZodString;
105
+ }, z.core.$strict>, z.ZodObject<{
106
+ scope: z.ZodLiteral<"block">;
107
+ target: z.ZodObject<{
108
+ blockId: z.ZodString;
109
+ }, z.core.$strict>;
110
+ schema: z.ZodLiteral<"authorbot.annotation/v1">;
111
+ id: z.ZodString;
112
+ kind: z.ZodEnum<{
113
+ comment: "comment";
114
+ suggestion: "suggestion";
115
+ }>;
116
+ chapter_id: z.ZodString;
117
+ chapter_revision: z.ZodNumber;
118
+ author: z.ZodString;
119
+ status: z.ZodEnum<{
120
+ open: "open";
121
+ work_item_created: "work_item_created";
122
+ accepted: "accepted";
123
+ resolved: "resolved";
124
+ rejected: "rejected";
125
+ withdrawn: "withdrawn";
126
+ superseded: "superseded";
127
+ orphaned: "orphaned";
128
+ needs_reanchor: "needs_reanchor";
129
+ }>;
130
+ created_at: z.ZodString;
131
+ }, z.core.$strict>, z.ZodObject<{
132
+ scope: z.ZodLiteral<"chapter">;
133
+ schema: z.ZodLiteral<"authorbot.annotation/v1">;
134
+ id: z.ZodString;
135
+ kind: z.ZodEnum<{
136
+ comment: "comment";
137
+ suggestion: "suggestion";
138
+ }>;
139
+ chapter_id: z.ZodString;
140
+ chapter_revision: z.ZodNumber;
141
+ author: z.ZodString;
142
+ status: z.ZodEnum<{
143
+ open: "open";
144
+ work_item_created: "work_item_created";
145
+ accepted: "accepted";
146
+ resolved: "resolved";
147
+ rejected: "rejected";
148
+ withdrawn: "withdrawn";
149
+ superseded: "superseded";
150
+ orphaned: "orphaned";
151
+ needs_reanchor: "needs_reanchor";
152
+ }>;
153
+ created_at: z.ZodString;
154
+ }, z.core.$strict>], "scope">;
155
+ export type Annotation = z.infer<typeof annotationSchema>;
156
+ /**
157
+ * Reply frontmatter `.authorbot/annotations/<id>/replies/<reply-id>.md` —
158
+ * `authorbot.reply/v1`. The contract pins only the schema ID; fields follow
159
+ * the Reply entity of design section 9.1 (ID, annotation ID, optional parent
160
+ * reply, author, timestamps). The reply body is the Markdown content itself.
161
+ */
162
+ export declare const replySchema: z.ZodObject<{
163
+ schema: z.ZodLiteral<"authorbot.reply/v1">;
164
+ id: z.ZodString;
165
+ annotation_id: z.ZodString;
166
+ parent_reply_id: z.ZodOptional<z.ZodString>;
167
+ author: z.ZodString;
168
+ created_at: z.ZodString;
169
+ updated_at: z.ZodOptional<z.ZodString>;
170
+ }, z.core.$strict>;
171
+ export type Reply = z.infer<typeof replySchema>;
172
+ //# sourceMappingURL=annotation.d.ts.map
@@ -0,0 +1,96 @@
1
+ import { z } from "zod";
2
+ import { actorRefSchema, timestampSchema, uuidv7Schema } from "./primitives.js";
3
+ /** Annotation lifecycle states (contract section 4, design section 9.4). */
4
+ export const ANNOTATION_STATUSES = [
5
+ "open",
6
+ "work_item_created",
7
+ "accepted",
8
+ "resolved",
9
+ "rejected",
10
+ "withdrawn",
11
+ "superseded",
12
+ "orphaned",
13
+ "needs_reanchor",
14
+ ];
15
+ export const annotationStatusSchema = z.enum(ANNOTATION_STATUSES);
16
+ export const ANNOTATION_KINDS = ["comment", "suggestion"];
17
+ export const annotationKindSchema = z.enum(ANNOTATION_KINDS);
18
+ /**
19
+ * Range target selector (design section 10.1). Selector field names are
20
+ * camelCase exactly as in the design payload: `blockId`, `textPosition`,
21
+ * `textQuote`. Positions are offsets into the normalized plain-text stream of
22
+ * the block, not raw HTML offsets.
23
+ */
24
+ export const textPositionSchema = z.strictObject({
25
+ start: z.number().int().min(0),
26
+ end: z.number().int().min(0),
27
+ });
28
+ /** Contract 2b §2.2: quote context is at most 32 characters each side. */
29
+ export const MAX_QUOTE_CONTEXT = 32;
30
+ /**
31
+ * Server-side ceiling for `textQuote.exact` (a selection within a single
32
+ * semantic block, so far below the 32 KiB body limit). Enforced here so an
33
+ * attacker-chosen selector can never smuggle megabytes into the annotations
34
+ * row and the committed `.authorbot/annotations/<id>/annotation.md` artifact.
35
+ */
36
+ export const MAX_QUOTE_EXACT = 8 * 1024;
37
+ export const textQuoteSchema = z.strictObject({
38
+ exact: z.string().min(1).max(MAX_QUOTE_EXACT),
39
+ prefix: z.string().max(MAX_QUOTE_CONTEXT).optional(),
40
+ suffix: z.string().max(MAX_QUOTE_CONTEXT).optional(),
41
+ });
42
+ export const rangeTargetSchema = z.strictObject({
43
+ blockId: uuidv7Schema,
44
+ textPosition: textPositionSchema,
45
+ textQuote: textQuoteSchema,
46
+ });
47
+ export const blockTargetSchema = z.strictObject({
48
+ blockId: uuidv7Schema,
49
+ });
50
+ const annotationBaseFields = {
51
+ schema: z.literal("authorbot.annotation/v1"),
52
+ id: uuidv7Schema,
53
+ kind: annotationKindSchema,
54
+ chapter_id: uuidv7Schema,
55
+ chapter_revision: z.number().int().min(1),
56
+ author: actorRefSchema,
57
+ status: annotationStatusSchema,
58
+ created_at: timestampSchema,
59
+ };
60
+ /**
61
+ * Annotation frontmatter `.authorbot/annotations/<id>/annotation.md` —
62
+ * `authorbot.annotation/v1` (contract section 4). `target` is required for
63
+ * `range` and `block` scopes and forbidden for `chapter` scope.
64
+ */
65
+ export const annotationSchema = z.discriminatedUnion("scope", [
66
+ z.strictObject({
67
+ ...annotationBaseFields,
68
+ scope: z.literal("range"),
69
+ target: rangeTargetSchema,
70
+ }),
71
+ z.strictObject({
72
+ ...annotationBaseFields,
73
+ scope: z.literal("block"),
74
+ target: blockTargetSchema,
75
+ }),
76
+ z.strictObject({
77
+ ...annotationBaseFields,
78
+ scope: z.literal("chapter"),
79
+ }),
80
+ ]);
81
+ /**
82
+ * Reply frontmatter `.authorbot/annotations/<id>/replies/<reply-id>.md` —
83
+ * `authorbot.reply/v1`. The contract pins only the schema ID; fields follow
84
+ * the Reply entity of design section 9.1 (ID, annotation ID, optional parent
85
+ * reply, author, timestamps). The reply body is the Markdown content itself.
86
+ */
87
+ export const replySchema = z.strictObject({
88
+ schema: z.literal("authorbot.reply/v1"),
89
+ id: uuidv7Schema,
90
+ annotation_id: uuidv7Schema,
91
+ parent_reply_id: uuidv7Schema.optional(),
92
+ author: actorRefSchema,
93
+ created_at: timestampSchema,
94
+ updated_at: timestampSchema.optional(),
95
+ });
96
+ //# sourceMappingURL=annotation.js.map
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ export declare const attributionEntrySchema: z.ZodObject<{
3
+ revision: z.ZodNumber;
4
+ actor: z.ZodString;
5
+ work_item_id: z.ZodOptional<z.ZodString>;
6
+ commit: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strict>;
8
+ export type AttributionEntry = z.infer<typeof attributionEntrySchema>;
9
+ /**
10
+ * Attribution record `.authorbot/attribution/<chapter-id>.yml` —
11
+ * `authorbot.attribution/v1` (contract section 4). At least one entry: the
12
+ * file only exists once a chapter revision has an author to attribute.
13
+ */
14
+ export declare const attributionSchema: z.ZodObject<{
15
+ schema: z.ZodLiteral<"authorbot.attribution/v1">;
16
+ chapter_id: z.ZodString;
17
+ entries: z.ZodArray<z.ZodObject<{
18
+ revision: z.ZodNumber;
19
+ actor: z.ZodString;
20
+ work_item_id: z.ZodOptional<z.ZodString>;
21
+ commit: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strict>>;
23
+ }, z.core.$strict>;
24
+ export type Attribution = z.infer<typeof attributionSchema>;
25
+ //# sourceMappingURL=attribution.d.ts.map
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+ import { actorRefSchema, commitShaSchema, uuidv7Schema } from "./primitives.js";
3
+ export const attributionEntrySchema = z.strictObject({
4
+ revision: z.number().int().min(1),
5
+ actor: actorRefSchema,
6
+ work_item_id: uuidv7Schema.optional(),
7
+ commit: commitShaSchema.optional(),
8
+ });
9
+ /**
10
+ * Attribution record `.authorbot/attribution/<chapter-id>.yml` —
11
+ * `authorbot.attribution/v1` (contract section 4). At least one entry: the
12
+ * file only exists once a chapter revision has an author to attribute.
13
+ */
14
+ export const attributionSchema = z.strictObject({
15
+ schema: z.literal("authorbot.attribution/v1"),
16
+ chapter_id: uuidv7Schema,
17
+ entries: z.array(attributionEntrySchema).min(1),
18
+ });
19
+ //# sourceMappingURL=attribution.js.map
package/dist/book.d.ts ADDED
@@ -0,0 +1,104 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * The four annotation policy modes (Phase 7 contract "Restricting"). Declared
4
+ * here rather than imported from `@authorbot/domain` because `@authorbot/schemas`
5
+ * is the leaf package every other one depends on and must not gain a dependency
6
+ * on the domain rules; `annotation-policy.test.ts` in the domain suite pins the
7
+ * two lists equal.
8
+ */
9
+ export declare const ANNOTATION_POLICY_MODES: readonly ["open", "approval-gated", "collaborators-only", "locked"];
10
+ export declare const annotationPolicySchema: z.ZodEnum<{
11
+ open: "open";
12
+ "approval-gated": "approval-gated";
13
+ "collaborators-only": "collaborators-only";
14
+ locked: "locked";
15
+ }>;
16
+ export type AnnotationPolicyMode = (typeof ANNOTATION_POLICY_MODES)[number];
17
+ /**
18
+ * Book config `book.yml` — `authorbot.book/v1` (design section 8.2).
19
+ * Optional sections default at load time; the schema does not inject defaults.
20
+ */
21
+ export declare const bookConfigSchema: z.ZodObject<{
22
+ schema: z.ZodLiteral<"authorbot.book/v1">;
23
+ id: z.ZodString;
24
+ title: z.ZodString;
25
+ slug: z.ZodString;
26
+ language: z.ZodString;
27
+ license: z.ZodOptional<z.ZodString>;
28
+ repository: z.ZodOptional<z.ZodObject<{
29
+ default_branch: z.ZodOptional<z.ZodString>;
30
+ }, z.core.$strict>>;
31
+ content: z.ZodOptional<z.ZodObject<{
32
+ chapters_glob: z.ZodOptional<z.ZodString>;
33
+ raw_html: z.ZodOptional<z.ZodBoolean>;
34
+ }, z.core.$strict>>;
35
+ planning: z.ZodOptional<z.ZodObject<{
36
+ method: z.ZodOptional<z.ZodString>;
37
+ outline: z.ZodOptional<z.ZodString>;
38
+ timeline: z.ZodOptional<z.ZodString>;
39
+ characters_glob: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strict>>;
41
+ publication: z.ZodOptional<z.ZodObject<{
42
+ chapter_url: z.ZodOptional<z.ZodString>;
43
+ api_url: z.ZodOptional<z.ZodString>;
44
+ show_revision: z.ZodOptional<z.ZodBoolean>;
45
+ show_attribution: z.ZodOptional<z.ZodBoolean>;
46
+ show_public_annotations: z.ZodOptional<z.ZodBoolean>;
47
+ }, z.core.$strict>>;
48
+ collaboration: z.ZodOptional<z.ZodObject<{
49
+ annotation_policy: z.ZodOptional<z.ZodEnum<{
50
+ open: "open";
51
+ "approval-gated": "approval-gated";
52
+ "collaborators-only": "collaborators-only";
53
+ locked: "locked";
54
+ }>>;
55
+ }, z.core.$strict>>;
56
+ governance: z.ZodOptional<z.ZodObject<{
57
+ rules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
58
+ version: z.ZodNumber;
59
+ trigger: z.ZodOptional<z.ZodEnum<{
60
+ vote_changed: "vote_changed";
61
+ }>>;
62
+ when: z.ZodUnion<readonly [z.ZodObject<{
63
+ all: z.ZodArray<z.ZodObject<{
64
+ metric: z.ZodString;
65
+ operator: z.ZodEnum<{
66
+ gte: "gte";
67
+ gt: "gt";
68
+ lte: "lte";
69
+ lt: "lt";
70
+ eq: "eq";
71
+ neq: "neq";
72
+ }>;
73
+ value: z.ZodNumber;
74
+ }, z.core.$strict>>;
75
+ }, z.core.$strict>, z.ZodObject<{
76
+ any: z.ZodArray<z.ZodObject<{
77
+ metric: z.ZodString;
78
+ operator: z.ZodEnum<{
79
+ gte: "gte";
80
+ gt: "gt";
81
+ lte: "lte";
82
+ lt: "lt";
83
+ eq: "eq";
84
+ neq: "neq";
85
+ }>;
86
+ value: z.ZodNumber;
87
+ }, z.core.$strict>>;
88
+ }, z.core.$strict>]>;
89
+ action: z.ZodObject<{
90
+ type: z.ZodLiteral<"create_work_item">;
91
+ work_type: z.ZodEnum<{
92
+ revise_range: "revise_range";
93
+ revise_block: "revise_block";
94
+ revise_chapter: "revise_chapter";
95
+ write_chapter: "write_chapter";
96
+ resolve_conflict: "resolve_conflict";
97
+ planning: "planning";
98
+ }>;
99
+ }, z.core.$strict>;
100
+ }, z.core.$strict>>>;
101
+ }, z.core.$strict>>;
102
+ }, z.core.$strict>;
103
+ export type BookConfig = z.infer<typeof bookConfigSchema>;
104
+ //# sourceMappingURL=book.d.ts.map
package/dist/book.js ADDED
@@ -0,0 +1,105 @@
1
+ import { z } from "zod";
2
+ import { rulesMapSchema } from "./instance.js";
3
+ import { slugSchema, uuidv7Schema } from "./primitives.js";
4
+ /**
5
+ * The four annotation policy modes (Phase 7 contract "Restricting"). Declared
6
+ * here rather than imported from `@authorbot/domain` because `@authorbot/schemas`
7
+ * is the leaf package every other one depends on and must not gain a dependency
8
+ * on the domain rules; `annotation-policy.test.ts` in the domain suite pins the
9
+ * two lists equal.
10
+ */
11
+ export const ANNOTATION_POLICY_MODES = [
12
+ "open",
13
+ "approval-gated",
14
+ "collaborators-only",
15
+ "locked",
16
+ ];
17
+ export const annotationPolicySchema = z.enum(ANNOTATION_POLICY_MODES);
18
+ /**
19
+ * Book config `book.yml` — `authorbot.book/v1` (design section 8.2).
20
+ * Optional sections default at load time; the schema does not inject defaults.
21
+ */
22
+ export const bookConfigSchema = z.strictObject({
23
+ schema: z.literal("authorbot.book/v1"),
24
+ id: uuidv7Schema,
25
+ title: z.string().min(1),
26
+ slug: slugSchema,
27
+ /** BCP 47-style language tag, e.g. `en` or `en-US`. */
28
+ language: z
29
+ .string()
30
+ .regex(/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{1,8})*$/, "must be a language tag like en-US"),
31
+ license: z.string().min(1).optional(),
32
+ repository: z
33
+ .strictObject({
34
+ default_branch: z.string().min(1).optional(),
35
+ })
36
+ .optional(),
37
+ content: z
38
+ .strictObject({
39
+ chapters_glob: z.string().min(1).optional(),
40
+ raw_html: z.boolean().optional(),
41
+ })
42
+ .optional(),
43
+ planning: z
44
+ .strictObject({
45
+ /** Method-neutral label (design section 1.2), e.g. `custom`, `snowflake`. */
46
+ method: z.string().min(1).optional(),
47
+ outline: z.string().min(1).optional(),
48
+ timeline: z.string().min(1).optional(),
49
+ characters_glob: z.string().min(1).optional(),
50
+ })
51
+ .optional(),
52
+ publication: z
53
+ .strictObject({
54
+ chapter_url: z.string().min(1).optional(),
55
+ /**
56
+ * Collaboration API base URL (Phase 2b contract §1); enables the
57
+ * annotation islands at build time. `authorbot build --api-url`
58
+ * overrides.
59
+ */
60
+ api_url: z.string().min(1).optional(),
61
+ show_revision: z.boolean().optional(),
62
+ show_attribution: z.boolean().optional(),
63
+ show_public_annotations: z.boolean().optional(),
64
+ })
65
+ .optional(),
66
+ /**
67
+ * Collaboration access (Phase 7 contract "Restricting").
68
+ *
69
+ * `annotation_policy` is who may comment and suggest, and whether what they
70
+ * write appears immediately: `open`, `approval-gated`, `collaborators-only`
71
+ * (the default when the section is absent), or `locked`. It lives in
72
+ * `book.yml` — versioned, diffable, reviewable — because it is an editorial
73
+ * decision about the book, made deliberately and changed rarely.
74
+ *
75
+ * The emergency controls deliberately do NOT live here. Freeze and
76
+ * pause-agents are operational state in the database (migration 0007
77
+ * explains why at length): they must take effect on the next request rather
78
+ * than the next commit, and they must work when the repository does not.
79
+ */
80
+ collaboration: z
81
+ .strictObject({
82
+ annotation_policy: annotationPolicySchema.optional(),
83
+ })
84
+ .optional(),
85
+ /**
86
+ * Governance rules (Phase 6 contract section 3.6, amending Phase 3 section
87
+ * 3). Rules live here — versioned, diffable, and reviewable alongside the
88
+ * prose they govern, and therefore editable from the Settings view. The
89
+ * `RULES_JSON` environment variable remains a *bootstrap default* for a book
90
+ * that has not set them; once `governance.rules` exists it wins outright.
91
+ *
92
+ * Absent and `{}` are deliberately different: absent means "not configured,
93
+ * fall back to the environment/design default", while an explicit empty map
94
+ * is rejected below because a book with zero rules would silently never
95
+ * promote anything.
96
+ */
97
+ governance: z
98
+ .strictObject({
99
+ rules: rulesMapSchema
100
+ .refine((rules) => Object.keys(rules).length > 0, "governance.rules must define at least one rule (omit the section to use the default)")
101
+ .optional(),
102
+ })
103
+ .optional(),
104
+ });
105
+ //# sourceMappingURL=book.js.map
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * One chapter as recorded in the build manifest (Phase 1 contract section 3,
4
+ * design section 17.2).
5
+ */
6
+ export declare const buildManifestChapterSchema: z.ZodObject<{
7
+ id: z.ZodString;
8
+ slug: z.ZodString;
9
+ revision: z.ZodNumber;
10
+ title: z.ZodString;
11
+ status: z.ZodEnum<{
12
+ draft: "draft";
13
+ proposed: "proposed";
14
+ published: "published";
15
+ archived: "archived";
16
+ }>;
17
+ }, z.core.$strict>;
18
+ export type BuildManifestChapter = z.infer<typeof buildManifestChapterSchema>;
19
+ /**
20
+ * Build manifest `authorbot-build.json` — `authorbot.build/v1` (Phase 1
21
+ * contract section 3). `commit` is null when the build ran outside a git
22
+ * work tree; `chapters` lists every chapter included in the build.
23
+ */
24
+ export declare const buildManifestSchema: z.ZodObject<{
25
+ schema: z.ZodLiteral<"authorbot.build/v1">;
26
+ commit: z.ZodNullable<z.ZodString>;
27
+ built_at: z.ZodString;
28
+ publisher_version: z.ZodString;
29
+ base_url: z.ZodOptional<z.ZodString>;
30
+ chapters: z.ZodArray<z.ZodObject<{
31
+ id: z.ZodString;
32
+ slug: z.ZodString;
33
+ revision: z.ZodNumber;
34
+ title: z.ZodString;
35
+ status: z.ZodEnum<{
36
+ draft: "draft";
37
+ proposed: "proposed";
38
+ published: "published";
39
+ archived: "archived";
40
+ }>;
41
+ }, z.core.$strict>>;
42
+ }, z.core.$strict>;
43
+ export type BuildManifest = z.infer<typeof buildManifestSchema>;
44
+ //# sourceMappingURL=build.d.ts.map
package/dist/build.js ADDED
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { chapterStatusSchema } from "./chapter.js";
3
+ import { commitShaSchema, slugSchema, timestampSchema, uuidv7Schema, } from "./primitives.js";
4
+ /**
5
+ * One chapter as recorded in the build manifest (Phase 1 contract section 3,
6
+ * design section 17.2).
7
+ */
8
+ export const buildManifestChapterSchema = z.strictObject({
9
+ id: uuidv7Schema,
10
+ slug: slugSchema,
11
+ revision: z.number().int().min(1),
12
+ title: z.string().min(1),
13
+ status: chapterStatusSchema,
14
+ });
15
+ /**
16
+ * Build manifest `authorbot-build.json` — `authorbot.build/v1` (Phase 1
17
+ * contract section 3). `commit` is null when the build ran outside a git
18
+ * work tree; `chapters` lists every chapter included in the build.
19
+ */
20
+ export const buildManifestSchema = z.strictObject({
21
+ schema: z.literal("authorbot.build/v1"),
22
+ commit: commitShaSchema.nullable(),
23
+ built_at: timestampSchema,
24
+ publisher_version: z.string().min(1),
25
+ base_url: z.string().min(1).optional(),
26
+ chapters: z.array(buildManifestChapterSchema),
27
+ });
28
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+ /** Chapter lifecycle states (contract section 4, design section 9.3). */
3
+ export declare const CHAPTER_STATUSES: readonly ["draft", "proposed", "published", "archived"];
4
+ export declare const chapterStatusSchema: z.ZodEnum<{
5
+ draft: "draft";
6
+ proposed: "proposed";
7
+ published: "published";
8
+ archived: "archived";
9
+ }>;
10
+ export type ChapterStatus = z.infer<typeof chapterStatusSchema>;
11
+ /**
12
+ * Chapter frontmatter — `authorbot.chapter/v1` (design section 8.3,
13
+ * contract section 4).
14
+ */
15
+ export declare const chapterFrontmatterSchema: z.ZodObject<{
16
+ schema: z.ZodLiteral<"authorbot.chapter/v1">;
17
+ id: z.ZodString;
18
+ slug: z.ZodString;
19
+ title: z.ZodString;
20
+ order: z.ZodNumber;
21
+ status: z.ZodEnum<{
22
+ draft: "draft";
23
+ proposed: "proposed";
24
+ published: "published";
25
+ archived: "archived";
26
+ }>;
27
+ revision: z.ZodNumber;
28
+ published_at: z.ZodOptional<z.ZodString>;
29
+ authors: z.ZodArray<z.ZodObject<{
30
+ actor: z.ZodString;
31
+ }, z.core.$strict>>;
32
+ summary: z.ZodOptional<z.ZodString>;
33
+ timeline_refs: z.ZodOptional<z.ZodArray<z.ZodString>>;
34
+ character_refs: z.ZodOptional<z.ZodArray<z.ZodString>>;
35
+ }, z.core.$strict>;
36
+ export type ChapterFrontmatter = z.infer<typeof chapterFrontmatterSchema>;
37
+ //# sourceMappingURL=chapter.d.ts.map