openapi.yaml yaml
2,518 lines 79.4 KB
Raw
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 19 hours ago
1 openapi: 3.0.3
2 info:
3 title: Knowtation Hub API
4 description: REST API for the Knowtation Hub (vault read/write, proposals, capture). Same contract as CLI/MCP where applicable.
5 version: 1.0.0
6 links:
7 - description: API contract (human-readable)
8 url: ./HUB-API.md
9
10 servers:
11 - url: /api/v1
12 description: Relative to Hub base URL (e.g. https://hub.example.com)
13
14 tags:
15 - name: Health
16 - name: Auth
17 - name: Notes
18 - name: Search
19 - name: Proposals
20 - name: Capture
21 - name: Flows
22
23 security:
24 - BearerAuth: []
25
26 paths:
27 /health:
28 get:
29 tags: [Health]
30 summary: Health check
31 security: []
32 responses:
33 '200':
34 description: Hub is up
35 content:
36 application/json:
37 schema: { type: object, properties: { ok: { type: boolean } }, required: [ok] }
38
39 /api/v1/auth/session:
40 get:
41 tags: [Auth]
42 summary: C7 Session introspection — current identity and scopes
43 description: |
44 Returns the verified identity and derived API scopes for the caller. Accepts only a
45 `Bearer` JWT in the `Authorization` header — no cookie required, making it safe to call
46 cross-origin from Scooling or any other consumer.
47
48 The response is derived entirely from the signed token — no database call is made.
49 Scopes are role-derived today (C4 will replace this with per-user explicit grants without
50 changing the response shape).
51 security:
52 - bearerAuth: []
53 responses:
54 '200':
55 description: Verified session
56 content:
57 application/json:
58 schema:
59 type: object
60 required: [sub, provider, id, name, role, iat, exp, scopes]
61 properties:
62 sub:
63 type: string
64 description: Canonical user ID (`provider:id`)
65 example: google:104164334692309763642
66 provider:
67 type: string
68 enum: [google, github]
69 id:
70 type: string
71 description: Provider-specific user ID
72 name:
73 type: string
74 description: Display name (empty for refresh-path tokens)
75 role:
76 type: string
77 enum: [admin, member]
78 iat:
79 type: integer
80 description: Token issued-at (Unix seconds)
81 exp:
82 type: integer
83 description: Token expires-at (Unix seconds)
84 scopes:
85 type: array
86 items: { type: string }
87 description: Derived API scopes. `admin` role → `[vault:read, vault:write, admin]`; `member` → `[vault:read, vault:write]`
88 example: [vault:read, vault:write]
89 '401':
90 description: Missing, expired, or tampered token
91 content:
92 application/json:
93 schema:
94 type: object
95 properties:
96 error: { type: string }
97 code: { type: string, enum: [UNAUTHORIZED] }
98
99 /auth/providers:
100 get:
101 tags: [Auth]
102 summary: OAuth providers configured
103 security: []
104 responses:
105 '200':
106 content:
107 application/json:
108 schema:
109 type: object
110 properties:
111 google: { type: boolean }
112 github: { type: boolean }
113
114 /notes/facets:
115 get:
116 tags: [Notes]
117 summary: Projects, tags, folders for filter dropdowns
118 responses:
119 '200':
120 content:
121 application/json:
122 schema:
123 type: object
124 properties:
125 projects: { type: array, items: { type: string } }
126 tags: { type: array, items: { type: string } }
127 folders: { type: array, items: { type: string } }
128
129 /notes:
130 get:
131 tags: [Notes]
132 summary: List notes
133 parameters:
134 - name: folder
135 in: query
136 schema: { type: string }
137 - name: project
138 in: query
139 schema: { type: string }
140 - name: tag
141 in: query
142 schema: { type: string }
143 - name: since
144 in: query
145 schema: { type: string }
146 - name: until
147 in: query
148 schema: { type: string }
149 - name: limit
150 in: query
151 schema: { type: integer, minimum: 0, maximum: 100 }
152 - name: offset
153 in: query
154 schema: { type: integer, minimum: 0 }
155 - name: order
156 in: query
157 schema: { type: string, enum: [date, date-asc] }
158 - name: fields
159 in: query
160 schema: { type: string, enum: [path, path+metadata, full] }
161 - name: count_only
162 in: query
163 schema: { type: boolean }
164 responses:
165 '200':
166 content:
167 application/json:
168 schema:
169 oneOf:
170 - type: object
171 properties:
172 notes: { type: array, items: { $ref: '#/components/schemas/NoteListItem' } }
173 total: { type: integer }
174 - type: object
175 properties:
176 total: { type: integer }
177 post:
178 tags: [Notes]
179 summary: Write or update a note
180 requestBody:
181 required: true
182 content:
183 application/json:
184 schema:
185 type: object
186 required: [path]
187 properties:
188 path: { type: string }
189 body: { type: string }
190 frontmatter: { type: object }
191 append: { type: boolean }
192 responses:
193 '200':
194 content:
195 application/json:
196 schema: { type: object, properties: { path: { type: string }, written: { type: boolean } } }
197 '400':
198 '500':
199 content:
200 application/json:
201 schema: { $ref: '#/components/schemas/Error' }
202
203 /notes/{path}:
204 get:
205 tags: [Notes]
206 summary: Get one note by path
207 parameters:
208 - name: path
209 in: path
210 required: true
211 schema: { type: string }
212 responses:
213 '200':
214 content:
215 application/json:
216 schema: { $ref: '#/components/schemas/NoteFull' }
217 '404':
218 content:
219 application/json:
220 schema: { $ref: '#/components/schemas/Error' }
221
222 /note-outline:
223 get:
224 tags: [Notes]
225 summary: Body-free NoteOutline headings for one note
226 description: >
227 Returns knowtation.note_outline/v1 metadata for one authorized vault-relative note.
228 The response excludes note body text, snippets, full frontmatter, absolute paths,
229 provider payloads, MCP resource URIs, summaries, vectors, OCR, PageIndex output,
230 persistence records, and write-back state.
231 parameters:
232 - name: path
233 in: query
234 required: true
235 schema: { type: string }
236 description: Vault-relative Markdown note path.
237 responses:
238 '200':
239 content:
240 application/json:
241 schema: { $ref: '#/components/schemas/NoteOutline' }
242 '400':
243 content:
244 application/json:
245 schema: { $ref: '#/components/schemas/Error' }
246 '401':
247 content:
248 application/json:
249 schema: { $ref: '#/components/schemas/Error' }
250 '403':
251 content:
252 application/json:
253 schema: { $ref: '#/components/schemas/Error' }
254 '404':
255 content:
256 application/json:
257 schema: { $ref: '#/components/schemas/Error' }
258 '502':
259 content:
260 application/json:
261 schema: { $ref: '#/components/schemas/Error' }
262
263 /document-tree:
264 get:
265 tags: [Notes]
266 summary: Body-free DocumentTree heading hierarchy for one note
267 description: >
268 Returns knowtation.document_tree/v0 metadata for one authorized vault-relative note.
269 The response excludes note body text, snippets, full frontmatter, absolute paths,
270 provider payloads, MCP resource URIs, summaries, vectors, OCR, PageIndex output,
271 persistence records, sidecars, LLM calls, and write-back state.
272 parameters:
273 - name: path
274 in: query
275 required: true
276 schema: { type: string }
277 description: Vault-relative Markdown note path.
278 responses:
279 '200':
280 content:
281 application/json:
282 schema: { $ref: '#/components/schemas/DocumentTree' }
283 '400':
284 content:
285 application/json:
286 schema: { $ref: '#/components/schemas/Error' }
287 '401':
288 content:
289 application/json:
290 schema: { $ref: '#/components/schemas/Error' }
291 '403':
292 content:
293 application/json:
294 schema: { $ref: '#/components/schemas/Error' }
295 '404':
296 content:
297 application/json:
298 schema: { $ref: '#/components/schemas/Error' }
299 '502':
300 content:
301 application/json:
302 schema: { $ref: '#/components/schemas/Error' }
303
304 /calendar/timeline:
305 get:
306 tags: [Calendar]
307 summary: Merged note-date and external-event timeline (self-hosted)
308 description: >
309 Returns knowtation.calendar_timeline/v0 items for an authorized vault.
310 Merges note-date buckets and stored calendar events. No OAuth tokens or connector secrets.
311 parameters:
312 - name: from
313 in: query
314 required: true
315 schema: { type: string }
316 description: Range start (YYYY-MM-DD or ISO8601).
317 - name: to
318 in: query
319 required: true
320 schema: { type: string }
321 description: Range end (YYYY-MM-DD or ISO8601).
322 - name: layers
323 in: query
324 required: false
325 schema: { type: string }
326 description: Comma-separated layers (`notes`, `events`). Default both.
327 - name: source_calendar_ids
328 in: query
329 required: false
330 schema: { type: string }
331 description: Comma-separated source calendar ids to include for the events layer.
332 responses:
333 '200':
334 content:
335 application/json:
336 schema: { $ref: '#/components/schemas/CalendarTimeline' }
337 '400':
338 content:
339 application/json:
340 schema: { $ref: '#/components/schemas/Error' }
341 '401':
342 content:
343 application/json:
344 schema: { $ref: '#/components/schemas/Error' }
345 '403':
346 content:
347 application/json:
348 schema: { $ref: '#/components/schemas/Error' }
349
350 /calendar/agent-context:
351 get:
352 tags: [Calendar]
353 summary: Tier-enforced calendar context for agents (self-hosted)
354 description: >
355 Returns knowtation.calendar_agent_context/v0 — redacted calendar events an agent
356 may see. Enforced server-side: calendars with enabled_for_agents=false contribute
357 nothing; per-calendar agent_context_tier_max and the org policy cap clamp the tier;
358 the v0 retrieval ceiling is tier 2. Agent visibility is independent of
359 enabled_for_display. Tier 1 omits the event summary; tier 0 returns no events.
360 Calendar text is untrusted prompt content.
361 parameters:
362 - name: from
363 in: query
364 required: true
365 schema: { type: string }
366 description: Range start (YYYY-MM-DD or ISO8601).
367 - name: to
368 in: query
369 required: true
370 schema: { type: string }
371 description: Range end (YYYY-MM-DD or ISO8601).
372 - name: agent_context_tier
373 in: query
374 required: true
375 schema: { type: integer, minimum: 0, maximum: 2 }
376 description: Requested agent tier (0 none, 1 busy blocks, 2 titles + label). Clamped by caps.
377 - name: source_calendar_ids
378 in: query
379 required: false
380 schema: { type: string }
381 description: Comma-separated source calendar ids to restrict the agent scope.
382 responses:
383 '200':
384 content:
385 application/json:
386 schema: { $ref: '#/components/schemas/CalendarAgentContext' }
387 '400':
388 content:
389 application/json:
390 schema: { $ref: '#/components/schemas/Error' }
391 '401':
392 content:
393 application/json:
394 schema: { $ref: '#/components/schemas/Error' }
395 '403':
396 content:
397 application/json:
398 schema: { $ref: '#/components/schemas/Error' }
399
400 /calendar/source-calendars:
401 get:
402 tags: [Calendar]
403 summary: List source calendars and display/agent toggles (self-hosted)
404 responses:
405 '200':
406 content:
407 application/json:
408 schema: { $ref: '#/components/schemas/SourceCalendarList' }
409 '401':
410 content:
411 application/json:
412 schema: { $ref: '#/components/schemas/Error' }
413 '403':
414 content:
415 application/json:
416 schema: { $ref: '#/components/schemas/Error' }
417
418 /calendar/source-calendars/{id}:
419 patch:
420 tags: [Calendar]
421 summary: Update source calendar display/agent toggles (self-hosted)
422 description: >
423 Partial update for enabled_for_display, enabled_for_agents, agent_context_tier_max (0–4),
424 and optional user_group. Org policy may cap agent_context_tier_max via
425 KNOWTATION_CALENDAR_AGENT_TIER_MAX_CAP or data/hub_calendar_policy.json.
426 parameters:
427 - name: id
428 in: path
429 required: true
430 schema: { type: string }
431 description: Source calendar id.
432 requestBody:
433 required: true
434 content:
435 application/json:
436 schema: { $ref: '#/components/schemas/SourceCalendarPatchRequest' }
437 responses:
438 '200':
439 content:
440 application/json:
441 schema: { $ref: '#/components/schemas/SourceCalendarPatchResult' }
442 '400':
443 content:
444 application/json:
445 schema: { $ref: '#/components/schemas/Error' }
446 '401':
447 content:
448 application/json:
449 schema: { $ref: '#/components/schemas/Error' }
450 '403':
451 content:
452 application/json:
453 schema: { $ref: '#/components/schemas/Error' }
454 '404':
455 content:
456 application/json:
457 schema: { $ref: '#/components/schemas/Error' }
458
459 /calendar/events/import:
460 post:
461 tags: [Calendar]
462 summary: Import ICS text into the local event store (read-only, self-hosted)
463 requestBody:
464 required: true
465 content:
466 application/json:
467 schema: { $ref: '#/components/schemas/CalendarIcsImportRequest' }
468 responses:
469 '200':
470 content:
471 application/json:
472 schema: { $ref: '#/components/schemas/CalendarIcsImportResult' }
473 '400':
474 content:
475 application/json:
476 schema: { $ref: '#/components/schemas/Error' }
477 '401':
478 content:
479 application/json:
480 schema: { $ref: '#/components/schemas/Error' }
481 '403':
482 content:
483 application/json:
484 schema: { $ref: '#/components/schemas/Error' }
485
486 /flows:
487 get:
488 tags: [Flows]
489 summary: List scope-visible flows (content-minimized)
490 description: >
491 Returns knowtation.flow_list/v0 summaries for flows visible in the caller's
492 authorized workspace scope. Scope query param narrows only — never widens.
493 Step bodies are never included in list responses.
494 parameters:
495 - name: scope
496 in: query
497 schema: { type: string, enum: [personal, project, org] }
498 description: Narrow within authorized scopes only.
499 - name: tag
500 in: query
501 schema: { type: string }
502 description: Filter by single tag membership.
503 - name: limit
504 in: query
505 schema: { type: integer, minimum: 1, maximum: 200 }
506 description: Max summaries (default 200).
507 responses:
508 '200':
509 content:
510 application/json:
511 schema: { $ref: '#/components/schemas/FlowListResponse' }
512 '400':
513 content:
514 application/json:
515 schema: { $ref: '#/components/schemas/Error' }
516 '401':
517 content:
518 application/json:
519 schema: { $ref: '#/components/schemas/Error' }
520 '403':
521 content:
522 application/json:
523 schema: { $ref: '#/components/schemas/Error' }
524 post:
525 tags: [Flows]
526 summary: Propose a new Flow (review-before-write)
527 description: >
528 Validates a knowtation.flow/v0 + flow_step/v0 bundle, resolves write
529 authority server-side (scope × role, deny-by-default), and creates a
530 standard proposal targeting the Flow's mirror note (SD-4). Returns a
531 knowtation.flow_proposal/v0 envelope (pointers/labels only). Gated by
532 FLOW_AUTHORING_WRITES — when off returns 403 FLOW_AUTHORING_DISABLED.
533 No Flow index write happens here; the index changes only at approve→apply.
534 requestBody:
535 required: true
536 content:
537 application/json:
538 schema: { $ref: '#/components/schemas/FlowProposeRequest' }
539 responses:
540 '201':
541 content:
542 application/json:
543 schema: { $ref: '#/components/schemas/FlowProposalResponse' }
544 '400':
545 content:
546 application/json:
547 schema: { $ref: '#/components/schemas/Error' }
548 '401':
549 content:
550 application/json:
551 schema: { $ref: '#/components/schemas/Error' }
552 '403':
553 content:
554 application/json:
555 schema: { $ref: '#/components/schemas/Error' }
556 '409':
557 content:
558 application/json:
559 schema: { $ref: '#/components/schemas/Error' }
560
561 /flows/import:
562 post:
563 tags: [Flows]
564 summary: Import a portable Flow bundle as a scope-checked proposal
565 description: >
566 Routes a portable { flow, steps } bundle through the same propose path.
567 The bundle scope is validated against the actor's write tier; unwritable
568 ⇒ 403 FLOW_IMPORT_SCOPE_DENIED, malformed ⇒ 400 FLOW_IMPORT_BUNDLE_MALFORMED.
569 Lineage pointers (external_ref / source_vault_hint) are preserved. Never
570 auto-applied — creates a proposed proposal. Gated by FLOW_AUTHORING_WRITES.
571 requestBody:
572 required: true
573 content:
574 application/json:
575 schema: { $ref: '#/components/schemas/FlowImportRequest' }
576 responses:
577 '201':
578 content:
579 application/json:
580 schema: { $ref: '#/components/schemas/FlowProposalResponse' }
581 '400':
582 content:
583 application/json:
584 schema: { $ref: '#/components/schemas/Error' }
585 '401':
586 content:
587 application/json:
588 schema: { $ref: '#/components/schemas/Error' }
589 '403':
590 content:
591 application/json:
592 schema: { $ref: '#/components/schemas/Error' }
593 '409':
594 content:
595 application/json:
596 schema: { $ref: '#/components/schemas/Error' }
597
598 /flows/capture/observe:
599 post:
600 tags: [Flows]
601 summary: Observe content-minimized session signals (capture detection)
602 description: >
603 Runs bounded structural detectors when FLOW_CAPTURE_DETECTION_ENABLED is on.
604 Creates/updates flow_candidate/v0 records; returns content-minimized summaries.
605 When detection is off, returns detection_authorized=false with no store mutation.
606 requestBody:
607 required: true
608 content:
609 application/json:
610 schema:
611 type: object
612 required: [session_id, step_sequence_refs, observed_counts]
613 responses:
614 '200':
615 description: Observe envelope
616 '400':
617 content:
618 application/json:
619 schema: { $ref: '#/components/schemas/Error' }
620 '403':
621 content:
622 application/json:
623 schema: { $ref: '#/components/schemas/Error' }
624
625 /flows/candidates:
626 get:
627 tags: [Flows]
628 summary: List flow capture candidates (read store)
629 description: Returns pending_review candidate summaries; read path does not require detection sub-gate.
630 parameters:
631 - name: scope
632 in: query
633 schema: { type: string, enum: [personal, project, org] }
634 - name: include_low_confidence
635 in: query
636 schema: { type: boolean }
637 - name: limit
638 in: query
639 schema: { type: integer, minimum: 1, maximum: 50 }
640 responses:
641 '200':
642 description: Candidate list envelope
643 '400':
644 content:
645 application/json:
646 schema: { $ref: '#/components/schemas/Error' }
647
648 /flows/candidates/{candidate_id}/propose:
649 post:
650 tags: [Flows]
651 summary: Propose candidate promotion (review-before-write)
652 description: >
653 Creates a flow_candidate_promote or flow_candidate_merge proposal.
654 Gated by FLOW_CAPTURE_WRITES_ENABLED (default off).
655 parameters:
656 - name: candidate_id
657 in: path
658 required: true
659 schema: { type: string }
660 requestBody:
661 required: true
662 content:
663 application/json:
664 schema:
665 type: object
666 required: [confirmed_scope, intent]
667 responses:
668 '201':
669 description: Capture proposal envelope
670 '403':
671 content:
672 application/json:
673 schema: { $ref: '#/components/schemas/Error' }
674 '404':
675 content:
676 application/json:
677 schema: { $ref: '#/components/schemas/Error' }
678 '409':
679 content:
680 application/json:
681 schema: { $ref: '#/components/schemas/Error' }
682
683 /flows/candidates/{candidate_id}/dismiss:
684 post:
685 tags: [Flows]
686 summary: Propose candidate dismissal
687 description: >
688 Creates a flow_candidate_dismiss proposal; on approve candidate status becomes rejected.
689 Gated by FLOW_CAPTURE_WRITES_ENABLED (default off).
690 parameters:
691 - name: candidate_id
692 in: path
693 required: true
694 schema: { type: string }
695 requestBody:
696 required: true
697 content:
698 application/json:
699 schema:
700 type: object
701 required: [intent]
702 responses:
703 '201':
704 description: Capture proposal envelope
705 '403':
706 content:
707 application/json:
708 schema: { $ref: '#/components/schemas/Error' }
709 '404':
710 content:
711 application/json:
712 schema: { $ref: '#/components/schemas/Error' }
713
714 /flows/{id}/proposals:
715 post:
716 tags: [Flows]
717 summary: Propose an edit to an existing Flow (review-before-write)
718 description: >
719 Like POST /flows but for an edit. Requires base_version + base_state_id
720 (the flowst1_ optimistic-concurrency token); a mismatch at propose or
721 approve time ⇒ 409 FLOW_LINEAGE_CONFLICT. flow.version must be strictly
722 greater than base_version. Editing a flow the actor cannot read ⇒ 404
723 unknown_flow (no existence leak). Gated by FLOW_AUTHORING_WRITES.
724 parameters:
725 - name: id
726 in: path
727 required: true
728 schema: { type: string }
729 description: Flow id (flow_<slug>); must match the bundle's flow_id.
730 requestBody:
731 required: true
732 content:
733 application/json:
734 schema: { $ref: '#/components/schemas/FlowProposeEditRequest' }
735 responses:
736 '201':
737 content:
738 application/json:
739 schema: { $ref: '#/components/schemas/FlowProposalResponse' }
740 '400':
741 content:
742 application/json:
743 schema: { $ref: '#/components/schemas/Error' }
744 '401':
745 content:
746 application/json:
747 schema: { $ref: '#/components/schemas/Error' }
748 '403':
749 content:
750 application/json:
751 schema: { $ref: '#/components/schemas/Error' }
752 '404':
753 content:
754 application/json:
755 schema: { $ref: '#/components/schemas/Error' }
756 '409':
757 content:
758 application/json:
759 schema: { $ref: '#/components/schemas/Error' }
760
761 /flows/{id}/projection:
762 get:
763 tags: [Flows]
764 summary: Derive a read-only harness projection of a canonical flow
765 description: >
766 Renders the canonical flow (latest visible, or pinned ?version) into the requested
767 harness as knowtation.flow_project/v0. Derived and read-only — generated_from_canonical
768 is always true and editable is always false. No secrets appear in rendered text.
769 parameters:
770 - name: id
771 in: path
772 required: true
773 schema: { type: string }
774 - name: harness
775 in: query
776 required: true
777 schema:
778 type: string
779 enum: [cursor_rule, cursor_skill, mcp_prompt, cli_runbook, agent_bundle]
780 - name: version
781 in: query
782 schema: { type: string }
783 responses:
784 '200':
785 content:
786 application/json:
787 schema: { $ref: '#/components/schemas/FlowProjectResponse' }
788 '400':
789 content:
790 application/json:
791 schema: { $ref: '#/components/schemas/Error' }
792 '401':
793 content:
794 application/json:
795 schema: { $ref: '#/components/schemas/Error' }
796 '403':
797 content:
798 application/json:
799 schema: { $ref: '#/components/schemas/Error' }
800 '404':
801 content:
802 application/json:
803 schema: { $ref: '#/components/schemas/Error' }
804
805 /flows/{id}/external-grants:
806 post:
807 tags: [Flows]
808 summary: Mint a short-lived external-agent grant (gated; default off)
809 description: >
810 Mints knowtation.flow_external_grant/v0 for a pinned flow version and requested tools.
811 Returns a one-time bearer at mint only. Requires FLOW_EXTERNAL_AGENT_ENABLED.
812 parameters:
813 - name: id
814 in: path
815 required: true
816 schema: { type: string }
817 requestBody:
818 required: true
819 content:
820 application/json:
821 schema: { $ref: '#/components/schemas/FlowExternalGrantMintRequest' }
822 responses:
823 '201':
824 content:
825 application/json:
826 schema: { $ref: '#/components/schemas/FlowExternalGrantMintResponse' }
827 '400':
828 content:
829 application/json:
830 schema: { $ref: '#/components/schemas/Error' }
831 '403':
832 content:
833 application/json:
834 schema: { $ref: '#/components/schemas/Error' }
835 '404':
836 content:
837 application/json:
838 schema: { $ref: '#/components/schemas/Error' }
839
840 /flows/external-grants:
841 get:
842 tags: [Flows]
843 summary: List external-agent grant metadata (no bearer)
844 parameters:
845 - name: flow_id
846 in: query
847 schema: { type: string }
848 responses:
849 '200':
850 content:
851 application/json:
852 schema: { $ref: '#/components/schemas/FlowExternalGrantListResponse' }
853 '403':
854 content:
855 application/json:
856 schema: { $ref: '#/components/schemas/Error' }
857
858 /flows/external-grants/{grant_id}:
859 delete:
860 tags: [Flows]
861 summary: Revoke an external-agent grant
862 parameters:
863 - name: grant_id
864 in: path
865 required: true
866 schema: { type: string }
867 responses:
868 '200':
869 content:
870 application/json:
871 schema: { $ref: '#/components/schemas/FlowExternalGrant' }
872 '403':
873 content:
874 application/json:
875 schema: { $ref: '#/components/schemas/Error' }
876 '404':
877 content:
878 application/json:
879 schema: { $ref: '#/components/schemas/Error' }
880
881 /flows/{id}:
882 get:
883 tags: [Flows]
884 summary: Get one flow definition + ordered steps
885 description: >
886 Returns knowtation.flow_get/v0 with full flow definition and steps in ascending
887 ordinal order. Missing and scope-invisible flows both return 404 unknown_flow.
888 Step text is untrusted input — returned verbatim as data.
889 parameters:
890 - name: id
891 in: path
892 required: true
893 schema: { type: string }
894 description: Flow id (flow_<slug>).
895 - name: version
896 in: query
897 schema: { type: string }
898 description: Pin semver version; default latest visible.
899 responses:
900 '200':
901 content:
902 application/json:
903 schema: { $ref: '#/components/schemas/FlowGetResponse' }
904 '400':
905 content:
906 application/json:
907 schema: { $ref: '#/components/schemas/Error' }
908 '401':
909 content:
910 application/json:
911 schema: { $ref: '#/components/schemas/Error' }
912 '403':
913 content:
914 application/json:
915 schema: { $ref: '#/components/schemas/Error' }
916 '404':
917 content:
918 application/json:
919 schema: { $ref: '#/components/schemas/Error' }
920
921 /flow-runs/{run_id}:
922 get:
923 tags: [Flows]
924 summary: Get one flow run by run id
925 description: >
926 Returns knowtation.flow_run/v0 for a scope-visible run. Missing and
927 scope-invisible runs both return 404 unknown_run.
928 parameters:
929 - name: run_id
930 in: path
931 required: true
932 schema: { type: string }
933 responses:
934 '200':
935 content:
936 application/json:
937 schema: { $ref: '#/components/schemas/FlowRunResponse' }
938 '404':
939 content:
940 application/json:
941 schema: { $ref: '#/components/schemas/Error' }
942
943 /flows/{id}/runs:
944 get:
945 tags: [Flows]
946 summary: List runs for a flow
947 parameters:
948 - name: id
949 in: path
950 required: true
951 schema: { type: string }
952 responses:
953 '200':
954 content:
955 application/json:
956 schema: { $ref: '#/components/schemas/FlowRunListResponse' }
957 post:
958 tags: [Flows]
959 summary: Start a flow run
960 description: >
961 Gated by FLOW_RUN_WRITES_ENABLED (default off). Pins flow_version for the run life.
962 parameters:
963 - name: id
964 in: path
965 required: true
966 schema: { type: string }
967 requestBody:
968 required: true
969 content:
970 application/json:
971 schema:
972 type: object
973 required: [flow_version]
974 properties:
975 flow_version: { type: string }
976 task_ref: { type: string }
977 external_ref: { type: string }
978 responses:
979 '201':
980 content:
981 application/json:
982 schema: { $ref: '#/components/schemas/FlowRunStartResponse' }
983 '403':
984 content:
985 application/json:
986 schema: { $ref: '#/components/schemas/Error' }
987
988 /flows/{id}/runs/{run_id}:
989 get:
990 tags: [Flows]
991 summary: Get one flow run
992 parameters:
993 - name: id
994 in: path
995 required: true
996 schema: { type: string }
997 - name: run_id
998 in: path
999 required: true
1000 schema: { type: string }
1001 responses:
1002 '200':
1003 content:
1004 application/json:
1005 schema: { $ref: '#/components/schemas/FlowRunResponse' }
1006 post:
1007 tags: [Flows]
1008 summary: Advance, record evidence, execute automatable, or submit review
1009 description: >
1010 Use dedicated sub-paths (/advance, /evidence, /execute-automatable, /submit-review).
1011 Run writes gated by FLOW_RUN_WRITES_ENABLED; automatable by FLOW_AUTOMATABLE_EXECUTION_ENABLED.
1012
1013 /flows/{id}/runs/{run_id}/advance:
1014 post:
1015 tags: [Flows]
1016 summary: Advance a step manually
1017 parameters:
1018 - name: id
1019 in: path
1020 required: true
1021 schema: { type: string }
1022 - name: run_id
1023 in: path
1024 required: true
1025 schema: { type: string }
1026 requestBody:
1027 required: true
1028 content:
1029 application/json:
1030 schema:
1031 type: object
1032 required: [step_id, to_status]
1033 properties:
1034 step_id: { type: string }
1035 to_status: { type: string }
1036 skip_reason: { type: string }
1037 responses:
1038 '200':
1039 content:
1040 application/json:
1041 schema: { $ref: '#/components/schemas/FlowRunResponse' }
1042
1043 /flows/{id}/runs/{run_id}/evidence:
1044 post:
1045 tags: [Flows]
1046 summary: Record evidence pointer on a step
1047 parameters:
1048 - name: id
1049 in: path
1050 required: true
1051 schema: { type: string }
1052 - name: run_id
1053 in: path
1054 required: true
1055 schema: { type: string }
1056 requestBody:
1057 required: true
1058 content:
1059 application/json:
1060 schema:
1061 type: object
1062 required: [step_id, evidence_ref, pointer_kind]
1063 properties:
1064 step_id: { type: string }
1065 evidence_ref: { type: string }
1066 pointer_kind: { type: string }
1067 responses:
1068 '200':
1069 content:
1070 application/json:
1071 schema: { $ref: '#/components/schemas/FlowRunResponse' }
1072
1073 /flows/{id}/runs/{run_id}/execute-automatable:
1074 post:
1075 tags: [Flows]
1076 summary: Execute an automatable step (server orchestration stub)
1077 description: Requires valid knowtation.flow_execution_consent/v0. Gated by FLOW_AUTOMATABLE_EXECUTION_ENABLED.
1078 parameters:
1079 - name: id
1080 in: path
1081 required: true
1082 schema: { type: string }
1083 - name: run_id
1084 in: path
1085 required: true
1086 schema: { type: string }
1087 requestBody:
1088 required: true
1089 content:
1090 application/json:
1091 schema:
1092 type: object
1093 required: [step_id, consent_id]
1094 properties:
1095 step_id: { type: string }
1096 consent_id: { type: string }
1097 model_lane: { type: string }
1098 dry_run: { type: boolean }
1099 responses:
1100 '200':
1101 content:
1102 application/json:
1103 schema: { $ref: '#/components/schemas/FlowExecuteAutomatableResponse' }
1104
1105 /flows/{id}/runs/{run_id}/submit-review:
1106 post:
1107 tags: [Flows]
1108 summary: Submit run outcome to review tray
1109 parameters:
1110 - name: id
1111 in: path
1112 required: true
1113 schema: { type: string }
1114 - name: run_id
1115 in: path
1116 required: true
1117 schema: { type: string }
1118 requestBody:
1119 required: true
1120 content:
1121 application/json:
1122 schema:
1123 type: object
1124 required: [intent]
1125 properties:
1126 intent: { type: string }
1127 responses:
1128 '200':
1129 content:
1130 application/json:
1131 schema: { $ref: '#/components/schemas/FlowRunSubmitReviewResponse' }
1132
1133 /flows/{id}/runs/{run_id}/consent:
1134 post:
1135 tags: [Flows]
1136 summary: Mint execution consent for automatable steps
1137 parameters:
1138 - name: id
1139 in: path
1140 required: true
1141 schema: { type: string }
1142 - name: run_id
1143 in: path
1144 required: true
1145 schema: { type: string }
1146 requestBody:
1147 required: true
1148 content:
1149 application/json:
1150 schema:
1151 type: object
1152 required: [allowed_lanes, cost_cap_units]
1153 properties:
1154 allowed_lanes: { type: array, items: { type: string } }
1155 cost_cap_units: { type: integer }
1156 ttl_seconds: { type: integer }
1157 responses:
1158 '201':
1159 content:
1160 application/json:
1161 schema: { $ref: '#/components/schemas/FlowExecutionConsentMintResponse' }
1162
1163 /metadata-facets:
1164 get:
1165 tags: [Notes]
1166 summary: Body-free MetadataFacets hints for one note
1167 description: >
1168 Returns knowtation.metadata_facets/v0 metadata for one authorized vault-relative note.
1169 The response excludes note body text, snippets, full frontmatter, absolute paths,
1170 provider payloads, MCP resource URIs, summaries, labels, vectors, OCR, PageIndex output,
1171 media metadata, memory events, persistence records, sidecars, LLM calls, and write-back state.
1172 parameters:
1173 - name: path
1174 in: query
1175 required: true
1176 schema: { type: string }
1177 description: Vault-relative Markdown note path.
1178 responses:
1179 '200':
1180 content:
1181 application/json:
1182 schema: { $ref: '#/components/schemas/MetadataFacets' }
1183 '400':
1184 content:
1185 application/json:
1186 schema: { $ref: '#/components/schemas/Error' }
1187 '401':
1188 content:
1189 application/json:
1190 schema: { $ref: '#/components/schemas/Error' }
1191 '403':
1192 content:
1193 application/json:
1194 schema: { $ref: '#/components/schemas/Error' }
1195 '404':
1196 content:
1197 application/json:
1198 schema: { $ref: '#/components/schemas/Error' }
1199 '502':
1200 content:
1201 application/json:
1202 schema: { $ref: '#/components/schemas/Error' }
1203
1204 /section-source:
1205 get:
1206 tags: [Notes]
1207 summary: Body-free SectionSource metadata for one note
1208 description: >
1209 Returns knowtation.section_source/v0 metadata for one authorized vault-relative note.
1210 The response excludes note body text, section body text, snippets, full frontmatter,
1211 line ranges, byte offsets, section body lengths, absolute paths, raw canister payloads,
1212 provider payloads, and MCP resource URIs.
1213 parameters:
1214 - name: path
1215 in: query
1216 required: true
1217 schema: { type: string }
1218 description: Vault-relative Markdown note path.
1219 responses:
1220 '200':
1221 content:
1222 application/json:
1223 schema: { $ref: '#/components/schemas/SectionSource' }
1224 '400':
1225 content:
1226 application/json:
1227 schema: { $ref: '#/components/schemas/Error' }
1228 '401':
1229 content:
1230 application/json:
1231 schema: { $ref: '#/components/schemas/Error' }
1232 '403':
1233 content:
1234 application/json:
1235 schema: { $ref: '#/components/schemas/Error' }
1236 '404':
1237 content:
1238 application/json:
1239 schema: { $ref: '#/components/schemas/Error' }
1240 '502':
1241 content:
1242 application/json:
1243 schema: { $ref: '#/components/schemas/Error' }
1244
1245 /index:
1246 post:
1247 tags: [Notes]
1248 summary: Re-run indexer (vault to vector store)
1249 responses:
1250 '200':
1251 content:
1252 application/json:
1253 schema:
1254 type: object
1255 properties:
1256 ok: { type: boolean }
1257 notesProcessed: { type: integer }
1258 chunksIndexed: { type: integer }
1259 vectors_deleted: { type: integer, description: Rows removed for this vault before upsert (hosted sqlite-vec) }
1260 '500':
1261 content:
1262 application/json:
1263 schema: { $ref: '#/components/schemas/Error' }
1264
1265 /export:
1266 post:
1267 tags: [Notes]
1268 summary: Export one note to content (returns body + filename for client download)
1269 requestBody:
1270 required: true
1271 content:
1272 application/json:
1273 schema:
1274 type: object
1275 required: [path]
1276 properties:
1277 path: { type: string }
1278 format: { type: string, enum: [md, html] }
1279 responses:
1280 '200':
1281 content:
1282 application/json:
1283 schema:
1284 type: object
1285 properties:
1286 content: { type: string }
1287 filename: { type: string }
1288 '400':
1289 content:
1290 application/json:
1291 schema: { $ref: '#/components/schemas/Error' }
1292 '404':
1293 content:
1294 application/json:
1295 schema: { $ref: '#/components/schemas/Error' }
1296
1297 /import:
1298 post:
1299 tags: [Notes]
1300 summary: Import from uploaded file or ZIP (multipart: source_type; file except for google-sheets; optional project, tags, spreadsheet_id for google-sheets)
1301 requestBody:
1302 required: true
1303 content:
1304 multipart/form-data:
1305 schema:
1306 type: object
1307 required: [source_type]
1308 properties:
1309 source_type:
1310 type: string
1311 description: Importer id. For google-sheets, omit file and set spreadsheet_id; optional sheets_range (A1 notation). See lib/import-source-types.mjs.
1312 file: { type: string, format: binary, description: Required for all importers except google-sheets. }
1313 spreadsheet_id:
1314 type: string
1315 description: Required when source_type is google-sheets (id from the Google Sheets URL).
1316 sheets_range:
1317 type: string
1318 description: Optional for google-sheets; A1 range. Omit to read the first sheet from A1.
1319 project: { type: string }
1320 output_dir: { type: string }
1321 tags: { type: string }
1322 responses:
1323 '200':
1324 content:
1325 application/json:
1326 schema:
1327 type: object
1328 properties:
1329 imported: { type: array, items: { type: object } }
1330 count: { type: integer }
1331 '400':
1332 content:
1333 application/json:
1334 schema: { $ref: '#/components/schemas/Error' }
1335 '500':
1336 content:
1337 application/json:
1338 schema: { $ref: '#/components/schemas/Error' }
1339
1340 /import-url:
1341 post:
1342 tags: [Notes]
1343 summary: Import from a public https URL (JSON body; editor/admin)
1344 requestBody:
1345 required: true
1346 content:
1347 application/json:
1348 schema:
1349 type: object
1350 required: [url]
1351 properties:
1352 url: { type: string, description: 'Full https URL' }
1353 mode: { type: string, enum: [auto, bookmark, extract], description: 'Capture mode (default auto)' }
1354 project: { type: string }
1355 output_dir: { type: string }
1356 tags: { oneOf: [{ type: string }, { type: array, items: { type: string } }] }
1357 responses:
1358 '200':
1359 content:
1360 application/json:
1361 schema:
1362 type: object
1363 properties:
1364 imported: { type: array, items: { type: object } }
1365 count: { type: integer }
1366 '400':
1367 content:
1368 application/json:
1369 schema: { $ref: '#/components/schemas/Error' }
1370 '500':
1371 content:
1372 application/json:
1373 schema: { $ref: '#/components/schemas/Error' }
1374
1375 /settings:
1376 get:
1377 tags: [Notes]
1378 summary: Config status for Settings UI (no secrets)
1379 responses:
1380 '200':
1381 content:
1382 application/json:
1383 schema:
1384 type: object
1385 properties:
1386 vault_path_display: { type: string }
1387 vault_git:
1388 type: object
1389 properties:
1390 enabled: { type: boolean }
1391 has_remote: { type: boolean }
1392 auto_commit: { type: boolean }
1393 auto_push: { type: boolean }
1394
1395 /vault/sync:
1396 post:
1397 tags: [Notes]
1398 summary: Manual vault backup (git add, commit, push)
1399 description: Self-hosted runs local git. Hosted (bridge) pushes notes as Markdown plus `.knowtation/backup/v1/snapshot.json` with full proposals.
1400 responses:
1401 '200':
1402 content:
1403 application/json:
1404 schema:
1405 type: object
1406 properties:
1407 ok: { type: boolean }
1408 message: { type: string }
1409 notesCount: { type: integer, description: Hosted bridge only }
1410 proposalsCount: { type: integer, description: Hosted bridge only }
1411 '400':
1412 content:
1413 application/json:
1414 schema: { $ref: '#/components/schemas/Error' }
1415 '500':
1416 content:
1417 application/json:
1418 schema: { $ref: '#/components/schemas/Error' }
1419
1420 /search:
1421 post:
1422 tags: [Search]
1423 summary: Vault search (semantic or keyword)
1424 requestBody:
1425 required: true
1426 content:
1427 application/json:
1428 schema:
1429 type: object
1430 required: [query]
1431 properties:
1432 query: { type: string }
1433 mode: { type: string, enum: [semantic, keyword], description: Omitted or semantic = vector search; keyword = substring/token match on note text }
1434 match: { type: string, enum: [phrase, all_terms], description: Keyword only; phrase = full query substring; all_terms = every token must appear }
1435 folder: { type: string }
1436 project: { type: string }
1437 tag: { type: string }
1438 since: { type: string }
1439 until: { type: string }
1440 chain: { type: string }
1441 entity: { type: string }
1442 episode: { type: string }
1443 limit: { type: integer }
1444 order: { type: string }
1445 fields: { type: string }
1446 content_scope: { type: string, enum: [notes, approval_logs], description: Narrow to normal notes vs approvals/ logs }
1447 snippetChars: { type: integer }
1448 count_only: { type: boolean }
1449 countOnly: { type: boolean }
1450 responses:
1451 '200':
1452 content:
1453 application/json:
1454 schema:
1455 type: object
1456 properties:
1457 results: { type: array, items: { $ref: '#/components/schemas/SearchResult' } }
1458 query: { type: string }
1459 mode: { type: string, enum: [semantic, keyword] }
1460 count: { type: integer, description: Present when count_only keyword search }
1461 '400':
1462 content:
1463 application/json:
1464 schema: { $ref: '#/components/schemas/Error' }
1465
1466 /proposals:
1467 get:
1468 tags: [Proposals]
1469 summary: List proposals
1470 parameters:
1471 - name: status
1472 in: query
1473 schema: { type: string }
1474 - name: limit
1475 in: query
1476 schema: { type: integer }
1477 - name: offset
1478 in: query
1479 schema: { type: integer }
1480 - name: label
1481 in: query
1482 description: Match if proposal labels include this string (case-insensitive)
1483 schema: { type: string }
1484 - name: source
1485 in: query
1486 schema: { type: string }
1487 - name: path_prefix
1488 in: query
1489 schema: { type: string }
1490 - name: evaluation_status
1491 in: query
1492 description: Filter by evaluation_status (none, pending, passed, failed, needs_changes)
1493 schema: { type: string }
1494 - name: review_queue
1495 in: query
1496 description: Exact match on proposal review_queue
1497 schema: { type: string }
1498 - name: review_severity
1499 in: query
1500 description: standard or elevated
1501 schema: { type: string }
1502 responses:
1503 '200':
1504 content:
1505 application/json:
1506 schema:
1507 type: object
1508 properties:
1509 proposals: { type: array, items: { $ref: '#/components/schemas/Proposal' } }
1510 total: { type: integer }
1511 post:
1512 tags: [Proposals]
1513 summary: Create proposal
1514 requestBody:
1515 content:
1516 application/json:
1517 schema:
1518 type: object
1519 properties:
1520 path: { type: string }
1521 body: { type: string }
1522 frontmatter: { type: object }
1523 intent: { type: string }
1524 base_state_id: { type: string }
1525 external_ref: { type: string }
1526 labels: { type: array, items: { type: string } }
1527 source: { type: string }
1528 responses:
1529 '201':
1530 content:
1531 application/json:
1532 schema:
1533 type: object
1534 properties:
1535 proposal_id: { type: string }
1536 path: { type: string }
1537 status: { type: string, enum: [proposed] }
1538 '400':
1539
1540 /proposals/{id}:
1541 get:
1542 tags: [Proposals]
1543 summary: Get one proposal
1544 parameters:
1545 - name: id
1546 in: path
1547 required: true
1548 schema: { type: string }
1549 responses:
1550 '200':
1551 content:
1552 application/json:
1553 schema: { $ref: '#/components/schemas/ProposalDetail' }
1554 '404':
1555
1556 /proposals/{id}/review-hints:
1557 post:
1558 tags: [Proposals]
1559 summary: Store async LLM review hints (canister; not a merge gate)
1560 parameters:
1561 - name: id
1562 in: path
1563 required: true
1564 schema: { type: string }
1565 requestBody:
1566 content:
1567 application/json:
1568 schema:
1569 type: object
1570 properties:
1571 review_hints: { type: string }
1572 review_hints_model: { type: string }
1573 responses:
1574 '200':
1575 content:
1576 application/json:
1577 schema:
1578 type: object
1579 properties:
1580 proposal_id: { type: string }
1581 ok: { type: boolean }
1582
1583 /proposals/{id}/evaluation:
1584 post:
1585 tags: [Proposals]
1586 summary: Submit human evaluation (admin or evaluator)
1587 parameters:
1588 - name: id
1589 in: path
1590 required: true
1591 schema: { type: string }
1592 requestBody:
1593 content:
1594 application/json:
1595 schema:
1596 type: object
1597 required: [outcome]
1598 properties:
1599 outcome:
1600 type: string
1601 enum: [pass, fail, needs_changes]
1602 checklist:
1603 type: array
1604 items:
1605 type: object
1606 properties:
1607 id: { type: string }
1608 passed: { type: boolean }
1609 grade: { type: string }
1610 comment: { type: string }
1611 responses:
1612 '200':
1613 content:
1614 application/json:
1615 schema: { $ref: '#/components/schemas/ProposalDetail' }
1616 '400':
1617 '404':
1618
1619 /proposals/{id}/approve:
1620 post:
1621 tags: [Proposals]
1622 summary: Apply proposal to vault
1623 parameters:
1624 - name: id
1625 in: path
1626 required: true
1627 schema: { type: string }
1628 requestBody:
1629 content:
1630 application/json:
1631 schema:
1632 type: object
1633 properties:
1634 base_state_id: { type: string }
1635 waiver_reason:
1636 type: string
1637 description: Admin override when evaluation is not passed (min length 3 after trim)
1638 external_ref:
1639 type: string
1640 description: Optional cross-system lineage id (e.g. Muse); server may resolve via MUSE_URL when omitted
1641 responses:
1642 '200':
1643 content:
1644 application/json:
1645 schema:
1646 type: object
1647 properties:
1648 proposal_id: { type: string }
1649 status: { type: string, enum: [approved] }
1650 external_ref: { type: string }
1651 '403':
1652 description: EVALUATION_REQUIRED — pass evaluation or provide waiver_reason
1653 '409':
1654 description: base_state_id mismatch (CONFLICT)
1655
1656 /proposals/{id}/enrich:
1657 post:
1658 tags: [Proposals]
1659 summary: Optional LLM summary and suggested labels (KNOWTATION_HUB_PROPOSAL_ENRICH=1)
1660 parameters:
1661 - name: id
1662 in: path
1663 required: true
1664 schema: { type: string }
1665 responses:
1666 '200':
1667 content:
1668 application/json:
1669 schema: { $ref: '#/components/schemas/ProposalDetail' }
1670 '400':
1671 description: >-
1672 ICP canister — suggested_labels_json or assistant_suggested_frontmatter_json is valid JSON
1673 but exceeds max length (4000 / 14000 characters) after validation.
1674 '404':
1675
1676 /proposals/{id}/discard:
1677 post:
1678 tags: [Proposals]
1679 summary: Discard proposal
1680 parameters:
1681 - name: id
1682 in: path
1683 required: true
1684 schema: { type: string }
1685 responses:
1686 '200':
1687 content:
1688 application/json:
1689 schema:
1690 type: object
1691 properties:
1692 proposal_id: { type: string }
1693 status: { type: string, enum: [discarded] }
1694
1695 /capture:
1696 post:
1697 tags: [Capture]
1698 summary: Ingest message into vault inbox (webhook-style)
1699 description: Same contract as capture-webhook. If CAPTURE_WEBHOOK_SECRET is set, require X-Webhook-Secret header.
1700 security: []
1701 requestBody:
1702 content:
1703 application/json:
1704 schema:
1705 type: object
1706 required: [body]
1707 properties:
1708 body: { type: string }
1709 source_id: { type: string }
1710 source: { type: string }
1711 project: { type: string }
1712 tags: { type: array, items: { type: string } }
1713 responses:
1714 '200':
1715 content:
1716 application/json:
1717 schema: { type: object, properties: { ok: { type: boolean }, path: { type: string } } }
1718 '400':
1719
1720 components:
1721 securitySchemes:
1722 BearerAuth:
1723 type: http
1724 scheme: bearer
1725 bearerFormat: JWT
1726
1727 schemas:
1728 Error:
1729 type: object
1730 properties:
1731 error: { type: string }
1732 code: { type: string }
1733
1734 NoteListItem:
1735 type: object
1736 properties:
1737 path: { type: string }
1738 title: { type: string, nullable: true }
1739 project: { type: string, nullable: true }
1740 tags: { type: array, items: { type: string } }
1741 date: { type: string, nullable: true }
1742
1743 NoteFull:
1744 type: object
1745 properties:
1746 path: { type: string }
1747 frontmatter: { type: object }
1748 body: { type: string }
1749
1750 SearchResult:
1751 type: object
1752 properties:
1753 path: { type: string }
1754 snippet: { type: string }
1755 score: { type: number }
1756 project: { type: string }
1757 tags: { type: array, items: { type: string } }
1758
1759 NoteOutline:
1760 type: object
1761 required: [schema, path, headings, truncated]
1762 properties:
1763 schema:
1764 type: string
1765 enum: [knowtation.note_outline/v1]
1766 path: { type: string }
1767 title: { type: string, nullable: true }
1768 headings:
1769 type: array
1770 maxItems: 500
1771 items: { $ref: '#/components/schemas/NoteOutlineHeading' }
1772 truncated: { type: boolean }
1773
1774 NoteOutlineHeading:
1775 type: object
1776 required: [level, text, id]
1777 properties:
1778 level: { type: integer, minimum: 1, maximum: 6 }
1779 text: { type: string }
1780 id: { type: string }
1781
1782 DocumentTree:
1783 type: object
1784 required: [schema, path, root, truncated]
1785 properties:
1786 schema:
1787 type: string
1788 enum: [knowtation.document_tree/v0]
1789 path: { type: string }
1790 title: { type: string, nullable: true }
1791 root:
1792 type: object
1793 required: [children]
1794 properties:
1795 children:
1796 type: array
1797 maxItems: 500
1798 items: { $ref: '#/components/schemas/DocumentTreeNode' }
1799 truncated: { type: boolean }
1800
1801 DocumentTreeNode:
1802 type: object
1803 required: [id, level, text, children]
1804 properties:
1805 id: { type: string }
1806 level: { type: integer, minimum: 1, maximum: 6 }
1807 text: { type: string }
1808 children:
1809 type: array
1810 items: { $ref: '#/components/schemas/DocumentTreeNode' }
1811
1812 MetadataFacets:
1813 type: object
1814 required: [schema, path, facets, inferred, truncated]
1815 properties:
1816 schema:
1817 type: string
1818 enum: [knowtation.metadata_facets/v0]
1819 path: { type: string }
1820 facets:
1821 type: object
1822 required: [project, tags, date, updated, causal_chain_id, entity, episode_id]
1823 properties:
1824 project: { type: string, nullable: true }
1825 tags:
1826 type: array
1827 maxItems: 100
1828 items: { type: string }
1829 date: { type: string, nullable: true }
1830 updated: { type: string, nullable: true }
1831 causal_chain_id: { type: string, nullable: true }
1832 entity:
1833 type: array
1834 maxItems: 100
1835 items: { type: string }
1836 episode_id: { type: string, nullable: true }
1837 inferred:
1838 type: object
1839 required: [folder, source_type]
1840 properties:
1841 folder: { type: string, nullable: true }
1842 source_type: { nullable: true, enum: [null] }
1843 truncated: { type: boolean }
1844
1845 SectionSource:
1846 type: object
1847 required: [schema, path, sections, truncated]
1848 properties:
1849 schema:
1850 type: string
1851 enum: [knowtation.section_source/v0]
1852 path: { type: string }
1853 title: { type: string, nullable: true }
1854 sections:
1855 type: array
1856 items: { $ref: '#/components/schemas/SectionSourceSection' }
1857 truncated: { type: boolean }
1858
1859 SectionSourceSection:
1860 type: object
1861 required:
1862 - section_id
1863 - heading_id
1864 - level
1865 - heading_path
1866 - heading_text
1867 - child_section_ids
1868 - body_available
1869 - body_returned
1870 - snippet_returned
1871 properties:
1872 section_id: { type: string }
1873 heading_id: { type: string }
1874 level: { type: integer, minimum: 1, maximum: 6 }
1875 heading_path: { type: array, items: { type: string } }
1876 heading_text: { type: string }
1877 child_section_ids: { type: array, items: { type: string } }
1878 body_available: { type: boolean }
1879 body_returned: { type: boolean, enum: [false] }
1880 snippet_returned: { type: boolean, enum: [false] }
1881
1882 Proposal:
1883 type: object
1884 properties:
1885 proposal_id: { type: string }
1886 path: { type: string }
1887 status: { type: string }
1888 intent: { type: string }
1889 base_state_id: { type: string }
1890 external_ref: { type: string }
1891 vault_id: { type: string }
1892 proposed_by: { type: string }
1893 labels: { type: array, items: { type: string } }
1894 source: { type: string }
1895 suggested_labels: { type: array, items: { type: string } }
1896 assistant_notes: { type: string }
1897 assistant_model: { type: string }
1898 assistant_at: { type: string }
1899 created_at: { type: string }
1900 updated_at: { type: string }
1901 evaluation_status:
1902 type: string
1903 enum: [none, pending, passed, failed, needs_changes]
1904 evaluation_grade: { type: string }
1905 evaluation_comment: { type: string }
1906 evaluated_by: { type: string }
1907 evaluated_at: { type: string }
1908 evaluation_waiver:
1909 type: object
1910 nullable: true
1911 properties:
1912 by: { type: string }
1913 at: { type: string }
1914 reason: { type: string }
1915 review_queue: { type: string }
1916 review_severity: { type: string, enum: [standard, elevated] }
1917 auto_flag_reasons:
1918 type: array
1919 items: { type: string }
1920 auto_flag_reasons_json: { type: string, description: JSON array string on canister }
1921 review_hints: { type: string }
1922 review_hints_at: { type: string }
1923 review_hints_model: { type: string }
1924 assistant_suggested_frontmatter:
1925 type: object
1926 description: Normalized SPEC-aligned suggested note metadata from Enrich (object on GET); omitted or empty on older proposals
1927 additionalProperties: true
1928
1929 ProposalDetail:
1930 allOf:
1931 - { $ref: '#/components/schemas/Proposal' }
1932 - type: object
1933 properties:
1934 body: { type: string }
1935 frontmatter: { type: object }
1936 evaluation_checklist:
1937 type: array
1938 items:
1939 type: object
1940 properties:
1941 id: { type: string }
1942 label: { type: string }
1943 passed: { type: boolean }
1944
1945 CalendarTimeline:
1946 type: object
1947 required: [schema, vault_id, from, to, layers, items]
1948 properties:
1949 schema:
1950 type: string
1951 enum: [knowtation.calendar_timeline/v0]
1952 vault_id: { type: string }
1953 from: { type: string }
1954 to: { type: string }
1955 layers:
1956 type: array
1957 items:
1958 type: string
1959 enum: [notes, events]
1960 items:
1961 type: array
1962 items:
1963 oneOf:
1964 - { $ref: '#/components/schemas/CalendarTimelineNoteItem' }
1965 - { $ref: '#/components/schemas/CalendarTimelineEventItem' }
1966
1967 CalendarTimelineNoteItem:
1968 type: object
1969 required: [kind, date, path, title, project, tags, sort_at]
1970 properties:
1971 kind:
1972 type: string
1973 enum: [note]
1974 date: { type: string }
1975 path: { type: string }
1976 title: { type: string, nullable: true }
1977 project: { type: string, nullable: true }
1978 tags:
1979 type: array
1980 items: { type: string }
1981 sort_at: { type: string }
1982
1983 CalendarTimelineEventItem:
1984 type: object
1985 required: [kind, event_id, source_calendar_id, start, end, timezone, summary, busy, status, calendar_label, sort_at]
1986 properties:
1987 kind:
1988 type: string
1989 enum: [event]
1990 event_id: { type: string }
1991 source_calendar_id: { type: string }
1992 start: { type: string }
1993 end: { type: string }
1994 timezone: { type: string }
1995 summary: { type: string, nullable: true }
1996 busy: { type: boolean }
1997 status:
1998 type: string
1999 enum: [confirmed, cancelled, tentative]
2000 calendar_label: { type: string, nullable: true }
2001 sort_at: { type: string }
2002
2003 CalendarAgentContext:
2004 type: object
2005 required: [schema, vault_id, from, to, requested_tier, effective_tier, policy_agent_context_tier_max_cap, source_calendars, items]
2006 properties:
2007 schema:
2008 type: string
2009 enum: [knowtation.calendar_agent_context/v0]
2010 vault_id: { type: string }
2011 from: { type: string }
2012 to: { type: string }
2013 requested_tier:
2014 type: integer
2015 minimum: 0
2016 maximum: 2
2017 effective_tier:
2018 type: integer
2019 minimum: 0
2020 maximum: 2
2021 description: Requested tier after the org policy cap is applied.
2022 policy_agent_context_tier_max_cap:
2023 type: integer
2024 minimum: 0
2025 maximum: 4
2026 source_calendars:
2027 type: array
2028 items: { $ref: '#/components/schemas/AgentContextCalendarSummary' }
2029 items:
2030 type: array
2031 items: { $ref: '#/components/schemas/CalendarAgentContextEventItem' }
2032
2033 AgentContextCalendarSummary:
2034 type: object
2035 required: [source_calendar_id, display_name, user_group, enabled_for_agents, agent_context_tier_max, effective_tier, event_count]
2036 properties:
2037 source_calendar_id: { type: string }
2038 display_name: { type: string }
2039 user_group:
2040 type: string
2041 nullable: true
2042 enum: [personal, work, school, other, null]
2043 enabled_for_agents: { type: boolean }
2044 agent_context_tier_max:
2045 type: integer
2046 minimum: 0
2047 maximum: 4
2048 effective_tier:
2049 type: integer
2050 minimum: 0
2051 maximum: 2
2052 event_count: { type: integer }
2053
2054 CalendarAgentContextEventItem:
2055 type: object
2056 required: [event_id, source_calendar_id, external_uid, start, end, timezone, busy, status, agent_tier]
2057 description: >
2058 Redacted event. `summary` and `calendar_label` are present only at tier 2;
2059 tier 1 omits the event title entirely.
2060 properties:
2061 event_id: { type: string }
2062 source_calendar_id: { type: string }
2063 external_uid: { type: string }
2064 start: { type: string }
2065 end: { type: string }
2066 timezone: { type: string }
2067 busy: { type: boolean }
2068 status:
2069 type: string
2070 enum: [confirmed, cancelled, tentative]
2071 agent_tier:
2072 type: integer
2073 minimum: 1
2074 maximum: 2
2075 summary: { type: string, nullable: true }
2076 calendar_label: { type: string, nullable: true }
2077
2078 SourceCalendarList:
2079 type: object
2080 required: [schema, vault_id, source_calendars]
2081 properties:
2082 schema:
2083 type: string
2084 enum: [knowtation.source_calendars/v0]
2085 vault_id: { type: string }
2086 source_calendars:
2087 type: array
2088 items: { $ref: '#/components/schemas/SourceCalendar' }
2089
2090 SourceCalendar:
2091 type: object
2092 required: [source_calendar_id, connector_id, display_name, enabled_for_sync, enabled_for_display, enabled_for_agents, agent_context_tier_max]
2093 properties:
2094 source_calendar_id: { type: string }
2095 connector_id: { type: string }
2096 display_name: { type: string }
2097 color: { type: string, nullable: true }
2098 user_group:
2099 type: string
2100 nullable: true
2101 enum: [personal, work, school, other, null]
2102 enabled_for_sync: { type: boolean }
2103 enabled_for_display: { type: boolean }
2104 enabled_for_agents: { type: boolean }
2105 agent_context_tier_max:
2106 type: integer
2107 minimum: 0
2108 maximum: 4
2109 provider: { type: string }
2110
2111 CalendarIcsImportRequest:
2112 type: object
2113 required: [ics_text]
2114 properties:
2115 ics_text: { type: string }
2116 display_name: { type: string }
2117 source_calendar_id: { type: string }
2118 connector_id: { type: string }
2119 default_timezone: { type: string }
2120
2121 CalendarIcsImportResult:
2122 type: object
2123 required: [schema, vault_id, source_calendar_id, connector_id, imported, updated]
2124 properties:
2125 schema:
2126 type: string
2127 enum: [knowtation.calendar_import/v0]
2128 vault_id: { type: string }
2129 source_calendar_id: { type: string }
2130 connector_id: { type: string }
2131 imported: { type: integer }
2132 updated: { type: integer }
2133
2134 SourceCalendarPatchRequest:
2135 type: object
2136 minProperties: 1
2137 properties:
2138 enabled_for_display: { type: boolean }
2139 enabled_for_agents: { type: boolean }
2140 agent_context_tier_max:
2141 type: integer
2142 minimum: 0
2143 maximum: 4
2144 user_group:
2145 type: string
2146 nullable: true
2147 enum: [personal, work, school, other, null]
2148
2149 SourceCalendarPatchResult:
2150 type: object
2151 required: [schema, vault_id, policy_agent_context_tier_max_cap, source_calendar]
2152 properties:
2153 schema:
2154 type: string
2155 enum: [knowtation.source_calendar_patch/v0]
2156 vault_id: { type: string }
2157 policy_agent_context_tier_max_cap:
2158 type: integer
2159 minimum: 0
2160 maximum: 4
2161 source_calendar: { $ref: '#/components/schemas/SourceCalendar' }
2162
2163 FlowListResponse:
2164 type: object
2165 required: [schema, vault_id, effective_scope, flows, truncated]
2166 properties:
2167 schema:
2168 type: string
2169 enum: [knowtation.flow_list/v0]
2170 vault_id: { type: string }
2171 effective_scope:
2172 type: string
2173 enum: [personal, project, org]
2174 flows:
2175 type: array
2176 maxItems: 200
2177 items: { $ref: '#/components/schemas/FlowSummary' }
2178 truncated: { type: boolean }
2179
2180 FlowSummary:
2181 type: object
2182 required: [schema, flow_id, title, version, scope, summary, tags, step_count, updated, truncated]
2183 properties:
2184 schema:
2185 type: string
2186 enum: [knowtation.flow/v0]
2187 flow_id: { type: string }
2188 title: { type: string }
2189 version: { type: string }
2190 scope:
2191 type: string
2192 enum: [personal, project, org]
2193 summary: { type: string }
2194 tags:
2195 type: array
2196 maxItems: 32
2197 items: { type: string }
2198 step_count: { type: integer, minimum: 0 }
2199 updated: { type: string }
2200 truncated: { type: boolean }
2201
2202 FlowGetResponse:
2203 type: object
2204 required: [schema, vault_id, flow, steps]
2205 properties:
2206 schema:
2207 type: string
2208 enum: [knowtation.flow_get/v0]
2209 vault_id: { type: string }
2210 flow: { $ref: '#/components/schemas/Flow' }
2211 steps:
2212 type: array
2213 maxItems: 100
2214 items: { $ref: '#/components/schemas/FlowStep' }
2215
2216 FlowProposeRequest:
2217 type: object
2218 required: [flow, steps, intent]
2219 description: Propose a new Flow. intent is untrusted and recorded verbatim.
2220 properties:
2221 flow: { $ref: '#/components/schemas/Flow' }
2222 steps:
2223 type: array
2224 maxItems: 100
2225 items: { $ref: '#/components/schemas/FlowStep' }
2226 intent: { type: string, minLength: 1 }
2227
2228 FlowProposeEditRequest:
2229 type: object
2230 required: [flow, steps, intent, base_version, base_state_id]
2231 description: >
2232 Propose an edit. base_version + base_state_id (flowst1_ token) gate
2233 optimistic concurrency; flow.version must exceed base_version.
2234 properties:
2235 flow: { $ref: '#/components/schemas/Flow' }
2236 steps:
2237 type: array
2238 maxItems: 100
2239 items: { $ref: '#/components/schemas/FlowStep' }
2240 intent: { type: string, minLength: 1 }
2241 base_version: { type: string }
2242 base_state_id: { type: string }
2243
2244 FlowImportRequest:
2245 type: object
2246 required: [bundle, intent]
2247 description: Import a portable bundle through the same scope-checked propose path.
2248 properties:
2249 bundle:
2250 type: object
2251 required: [flow, steps]
2252 properties:
2253 flow: { $ref: '#/components/schemas/Flow' }
2254 steps:
2255 type: array
2256 maxItems: 100
2257 items: { $ref: '#/components/schemas/FlowStep' }
2258 intent: { type: string, minLength: 1 }
2259 external_ref: { type: string }
2260 source_vault_hint: { type: string }
2261
2262 FlowProposalResponse:
2263 type: object
2264 required: [schema, proposal_id, flow_id, scope, auto_approvable, status, review_queue]
2265 description: >
2266 knowtation.flow_proposal/v0 envelope — pointers/labels only, never a
2267 rendered Flow body or secret. base_version/base_state_id are null for new.
2268 properties:
2269 schema:
2270 type: string
2271 enum: [knowtation.flow_proposal/v0]
2272 proposal_id: { type: string }
2273 flow_id: { type: string }
2274 base_version: { type: string, nullable: true }
2275 base_state_id: { type: string, nullable: true }
2276 scope:
2277 type: string
2278 enum: [personal, project, org]
2279 auto_approvable: { type: boolean }
2280 status:
2281 type: string
2282 enum: [proposed]
2283 review_queue: { type: string }
2284
2285 FlowExternalGrantMintRequest:
2286 type: object
2287 required: [flow_version, requested_tools]
2288 properties:
2289 flow_version: { type: string }
2290 requested_tools:
2291 type: array
2292 minItems: 1
2293 items: { type: string }
2294 ttl_seconds: { type: integer, minimum: 1 }
2295 actor_label: { type: string }
2296
2297 FlowExternalGrant:
2298 type: object
2299 required:
2300 - schema
2301 - grant_id
2302 - vault_id
2303 - scope
2304 - flow_id
2305 - flow_version
2306 - allowed_tools
2307 - allowed_harnesses
2308 - expires_at
2309 - issued_at
2310 - revoked_at
2311 - actor_hash
2312 - invocation_count
2313 properties:
2314 schema:
2315 type: string
2316 enum: [knowtation.flow_external_grant/v0]
2317 grant_id: { type: string }
2318 vault_id: { type: string }
2319 scope:
2320 type: string
2321 enum: [personal, project, org]
2322 flow_id: { type: string }
2323 flow_version: { type: string }
2324 allowed_tools:
2325 type: array
2326 items: { type: string }
2327 allowed_harnesses:
2328 type: array
2329 items: { type: string }
2330 expires_at: { type: string, format: date-time }
2331 issued_at: { type: string, format: date-time }
2332 revoked_at: { type: string, format: date-time, nullable: true }
2333 actor_hash: { type: string }
2334 max_invocations: { type: integer }
2335 invocation_count: { type: integer }
2336
2337 FlowExternalGrantMintResponse:
2338 type: object
2339 required: [schema, grant, bearer, expires_at]
2340 properties:
2341 schema:
2342 type: string
2343 enum: [knowtation.flow_external_grant_mint/v0]
2344 grant: { $ref: '#/components/schemas/FlowExternalGrant' }
2345 bearer: { type: string }
2346 expires_at: { type: string, format: date-time }
2347
2348 FlowExternalGrantListResponse:
2349 type: object
2350 required: [schema, vault_id, grants]
2351 properties:
2352 schema:
2353 type: string
2354 enum: [knowtation.flow_external_grant_list/v0]
2355 vault_id: { type: string }
2356 grants:
2357 type: array
2358 items: { $ref: '#/components/schemas/FlowExternalGrant' }
2359
2360 FlowProjectResponse:
2361 type: object
2362 required: [schema, vault_id, projection, staleness, generator]
2363 properties:
2364 schema:
2365 type: string
2366 enum: [knowtation.flow_project/v0]
2367 vault_id: { type: string }
2368 projection: { $ref: '#/components/schemas/FlowProjection' }
2369 staleness: { $ref: '#/components/schemas/FlowProjectionStaleness' }
2370 generator: { $ref: '#/components/schemas/FlowProjectionGenerator' }
2371
2372 FlowProjection:
2373 type: object
2374 required: [schema, flow_id, flow_version, harness, rendered, generated_from_canonical, editable]
2375 properties:
2376 schema:
2377 type: string
2378 enum: [knowtation.flow_projection/v0]
2379 flow_id: { type: string }
2380 flow_version: { type: string }
2381 harness:
2382 type: string
2383 enum: [cursor_rule, cursor_skill, mcp_prompt, cli_runbook, agent_bundle]
2384 rendered:
2385 type: string
2386 maxLength: 65536
2387 generated_from_canonical:
2388 type: boolean
2389 enum: [true]
2390 editable:
2391 type: boolean
2392 enum: [false]
2393 fidelity:
2394 type: object
2395 required: [dropped_fields]
2396 properties:
2397 dropped_fields:
2398 type: array
2399 items: { type: string }
2400 notes: { type: string }
2401
2402 FlowProjectionStaleness:
2403 type: object
2404 required: [stale, projection_version, latest_version]
2405 properties:
2406 stale: { type: boolean }
2407 projection_version: { type: string }
2408 latest_version: { type: string }
2409
2410 FlowProjectionGenerator:
2411 type: object
2412 required: [generator_version, content_hash, generated_at]
2413 properties:
2414 generator_version: { type: string }
2415 content_hash: { type: string }
2416 generated_at: { type: string }
2417
2418 Flow:
2419 type: object
2420 required: [schema, flow_id, title, version, scope, summary, steps, updated, truncated]
2421 properties:
2422 schema:
2423 type: string
2424 enum: [knowtation.flow/v0]
2425 flow_id: { type: string }
2426 title: { type: string }
2427 version: { type: string }
2428 scope:
2429 type: string
2430 enum: [personal, project, org]
2431 summary: { type: string }
2432 tags:
2433 type: array
2434 maxItems: 32
2435 items: { type: string }
2436 steps:
2437 type: array
2438 maxItems: 100
2439 items: { type: string }
2440 inputs:
2441 type: array
2442 items:
2443 type: object
2444 required: [name, type, required]
2445 properties:
2446 name: { type: string }
2447 type: { type: string }
2448 required: { type: boolean }
2449 vault_mirror_path: { type: string, nullable: true }
2450 updated: { type: string }
2451 truncated: { type: boolean }
2452
2453 FlowStep:
2454 type: object
2455 required: [schema, step_id, flow_id, ordinal, owned_job, instruction, trigger, when_not_to_run, boundaries, output_shape, verification, automatable]
2456 properties:
2457 schema:
2458 type: string
2459 enum: [knowtation.flow_step/v0]
2460 step_id: { type: string }
2461 flow_id: { type: string }
2462 ordinal: { type: integer, minimum: 1 }
2463 owned_job: { type: string }
2464 instruction: { type: string }
2465 trigger: { type: string }
2466 when_not_to_run: { type: string }
2467 requires:
2468 type: array
2469 items:
2470 type: object
2471 required: [kind, id]
2472 properties:
2473 kind:
2474 type: string
2475 enum: [vault_scope, tool, file, artifact]
2476 id: { type: string }
2477 boundaries:
2478 type: array
2479 items: { type: string }
2480 skill_refs:
2481 type: array
2482 items:
2483 type: object
2484 required: [kind, id]
2485 properties:
2486 kind:
2487 type: string
2488 enum: [mcp_prompt, skill_pack, cli, external_tool]
2489 id: { type: string }
2490 inputs:
2491 type: array
2492 items:
2493 type: object
2494 required: [name, from]
2495 properties:
2496 name: { type: string }
2497 from: { type: string }
2498 outputs:
2499 type: array
2500 items:
2501 type: object
2502 required: [name, type]
2503 properties:
2504 name: { type: string }
2505 type: { type: string }
2506 output_shape: { type: string }
2507 verification:
2508 type: object
2509 required: [kind, evidence_required, description]
2510 properties:
2511 kind:
2512 type: string
2513 enum: [human_review, artifact_exists, value_match, test_pass, agent_check]
2514 evidence_required: { type: boolean }
2515 description: { type: string }
2516 automatable:
2517 type: string
2518 enum: [manual, agent_assisted, automatable]
File History 1 commit
sha256:8915fe406161f95c1681f9469375e7bae5b28c884f00bedbdef65e4b0cd0738d docs(flow): commit FLOW-V0-SPEC.md hygiene for 7A-INT merge Human 19 hours ago