@owlmeans/viable-common 0.0.46 → 0.0.47

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 (153) hide show
  1. package/README.md +163 -14
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/agent-presentation/SKILL.md +1 -1
  4. package/agent-meta/skills/viable-common/SKILL.md +122 -30
  5. package/build/connect/account/types.d.ts +81 -0
  6. package/build/connect/account/types.d.ts.map +1 -0
  7. package/build/connect/account/types.js +2 -0
  8. package/build/connect/account/types.js.map +1 -0
  9. package/build/connect/branding/types.d.ts +26 -4
  10. package/build/connect/branding/types.d.ts.map +1 -1
  11. package/build/connect/call/types.d.ts +28 -0
  12. package/build/connect/call/types.d.ts.map +1 -0
  13. package/build/connect/call/types.js +2 -0
  14. package/build/connect/call/types.js.map +1 -0
  15. package/build/connect/config/types.d.ts +45 -0
  16. package/build/connect/config/types.d.ts.map +1 -0
  17. package/build/connect/config/types.js +2 -0
  18. package/build/connect/config/types.js.map +1 -0
  19. package/build/connect/consts.d.ts +383 -1
  20. package/build/connect/consts.d.ts.map +1 -1
  21. package/build/connect/consts.js +387 -1
  22. package/build/connect/consts.js.map +1 -1
  23. package/build/connect/conversion/types.d.ts +24 -0
  24. package/build/connect/conversion/types.d.ts.map +1 -1
  25. package/build/connect/entrypoints/types.d.ts +22 -13
  26. package/build/connect/entrypoints/types.d.ts.map +1 -1
  27. package/build/connect/entrypoints.d.ts +441 -8
  28. package/build/connect/entrypoints.d.ts.map +1 -1
  29. package/build/connect/entrypoints.js +292 -9
  30. package/build/connect/entrypoints.js.map +1 -1
  31. package/build/connect/errors.d.ts +12 -0
  32. package/build/connect/errors.d.ts.map +1 -1
  33. package/build/connect/errors.js +16 -0
  34. package/build/connect/errors.js.map +1 -1
  35. package/build/connect/feed/types.d.ts +71 -0
  36. package/build/connect/feed/types.d.ts.map +1 -0
  37. package/build/connect/feed/types.js +2 -0
  38. package/build/connect/feed/types.js.map +1 -0
  39. package/build/connect/files/types.d.ts +34 -0
  40. package/build/connect/files/types.d.ts.map +1 -0
  41. package/build/connect/files/types.js +2 -0
  42. package/build/connect/files/types.js.map +1 -0
  43. package/build/connect/git/types.d.ts +170 -0
  44. package/build/connect/git/types.d.ts.map +1 -0
  45. package/build/connect/git/types.js +14 -0
  46. package/build/connect/git/types.js.map +1 -0
  47. package/build/connect/iam/types.d.ts +25 -0
  48. package/build/connect/iam/types.d.ts.map +1 -0
  49. package/build/connect/iam/types.js +8 -0
  50. package/build/connect/iam/types.js.map +1 -0
  51. package/build/connect/index.d.ts +9 -0
  52. package/build/connect/index.d.ts.map +1 -1
  53. package/build/connect/production/types.d.ts +65 -0
  54. package/build/connect/production/types.d.ts.map +1 -0
  55. package/build/connect/production/types.js +2 -0
  56. package/build/connect/production/types.js.map +1 -0
  57. package/build/connect/project/types.d.ts +23 -16
  58. package/build/connect/project/types.d.ts.map +1 -1
  59. package/build/connect/references/types.d.ts +424 -2
  60. package/build/connect/references/types.d.ts.map +1 -1
  61. package/build/connect/references.d.ts.map +1 -1
  62. package/build/connect/references.js +122 -0
  63. package/build/connect/references.js.map +1 -1
  64. package/build/connect/schemas.d.ts +65 -2
  65. package/build/connect/schemas.d.ts.map +1 -1
  66. package/build/connect/schemas.js +306 -1
  67. package/build/connect/schemas.js.map +1 -1
  68. package/build/connect/settings/types.d.ts +0 -25
  69. package/build/connect/settings/types.d.ts.map +1 -1
  70. package/build/connect/slot/types.d.ts +24 -0
  71. package/build/connect/slot/types.d.ts.map +1 -0
  72. package/build/connect/slot/types.js +2 -0
  73. package/build/connect/slot/types.js.map +1 -0
  74. package/build/convert/record/types.d.ts +0 -9
  75. package/build/convert/record/types.d.ts.map +1 -1
  76. package/build/convert/schemas.d.ts +2 -5
  77. package/build/convert/schemas.d.ts.map +1 -1
  78. package/build/convert/schemas.js +2 -15
  79. package/build/convert/schemas.js.map +1 -1
  80. package/build/iam-console/consts.d.ts +13 -0
  81. package/build/iam-console/consts.d.ts.map +1 -0
  82. package/build/iam-console/consts.js +13 -0
  83. package/build/iam-console/consts.js.map +1 -0
  84. package/build/iam-console/consts.local.d.ts +123 -0
  85. package/build/iam-console/consts.local.d.ts.map +1 -0
  86. package/build/iam-console/consts.local.js +50 -0
  87. package/build/iam-console/consts.local.js.map +1 -0
  88. package/build/iam-console/index.d.ts +4 -0
  89. package/build/iam-console/index.d.ts.map +1 -0
  90. package/build/iam-console/index.js +3 -0
  91. package/build/iam-console/index.js.map +1 -0
  92. package/build/iam-console/schemas.d.ts +38 -0
  93. package/build/iam-console/schemas.d.ts.map +1 -0
  94. package/build/iam-console/schemas.js +217 -0
  95. package/build/iam-console/schemas.js.map +1 -0
  96. package/build/iam-console/types.d.ts +140 -0
  97. package/build/iam-console/types.d.ts.map +1 -0
  98. package/build/iam-console/types.js +2 -0
  99. package/build/iam-console/types.js.map +1 -0
  100. package/build/index.d.ts +1 -0
  101. package/build/index.d.ts.map +1 -1
  102. package/build/index.js +1 -0
  103. package/build/index.js.map +1 -1
  104. package/build/legal/consts.d.ts +33 -2
  105. package/build/legal/consts.d.ts.map +1 -1
  106. package/build/legal/consts.js +11 -3
  107. package/build/legal/consts.js.map +1 -1
  108. package/build/legal/types.d.ts +8 -1
  109. package/build/legal/types.d.ts.map +1 -1
  110. package/build/planning/schemas.d.ts.map +1 -1
  111. package/build/planning/schemas.js +0 -1
  112. package/build/planning/schemas.js.map +1 -1
  113. package/build/planning/types.d.ts +0 -2
  114. package/build/planning/types.d.ts.map +1 -1
  115. package/package.json +11 -2
  116. package/src/connect/account/types.ts +91 -0
  117. package/src/connect/branding/types.ts +28 -4
  118. package/src/connect/call/types.ts +31 -0
  119. package/src/connect/config/types.ts +51 -0
  120. package/src/connect/consts.ts +400 -1
  121. package/src/connect/conversion/types.ts +25 -0
  122. package/src/connect/entrypoints/types.ts +22 -7
  123. package/src/connect/entrypoints.ts +592 -15
  124. package/src/connect/errors.ts +18 -0
  125. package/src/connect/feed/types.ts +76 -0
  126. package/src/connect/files/types.ts +38 -0
  127. package/src/connect/git/types.ts +187 -0
  128. package/src/connect/iam/types.ts +28 -0
  129. package/src/connect/index.ts +9 -0
  130. package/src/connect/production/types.ts +71 -0
  131. package/src/connect/project/types.ts +25 -12
  132. package/src/connect/references/types.ts +166 -5
  133. package/src/connect/references.ts +210 -5
  134. package/src/connect/schemas.ts +366 -5
  135. package/src/connect/settings/types.ts +0 -25
  136. package/src/connect/slot/types.ts +24 -0
  137. package/src/convert/record/types.ts +0 -11
  138. package/src/convert/schemas.ts +3 -19
  139. package/src/iam-console/consts.local.ts +64 -0
  140. package/src/iam-console/consts.ts +15 -0
  141. package/src/iam-console/index.ts +3 -0
  142. package/src/iam-console/schemas.ts +251 -0
  143. package/src/iam-console/types.ts +165 -0
  144. package/src/index.ts +1 -0
  145. package/src/legal/consts.ts +13 -5
  146. package/src/legal/types.ts +12 -1
  147. package/src/planning/schemas.ts +0 -1
  148. package/src/planning/types.ts +0 -2
  149. package/tests/connect-convert.spec.ts +6 -2
  150. package/tests/connect-entrypoints.spec.ts +554 -16
  151. package/tests/error-status.spec.ts +2 -1
  152. package/tests/iam-console.spec.ts +89 -0
  153. package/tests/planning.spec.ts +8 -0
package/README.md CHANGED
@@ -6,25 +6,155 @@ Viable turns a description into a running full-stack application. Four runtimes
6
6
  about every name involved — the platform API services, the agent, the publisher that runs inside a project
7
7
  slot, and the connector SDK on a developer's machine — so each of those names is declared here
8
8
  once and imported by all of them. There is no runtime in this package: no `@langchain/*`, no
9
- filesystem, no inference SDK. It is safe to import from a browser bundle.
9
+ filesystem, no inference SDK. It is safe to import from a browser bundle, so it holds names and
10
+ shapes only: data that only the agent library reads (skill bodies, persona prompts, the blueprint
11
+ case table, BA model-answer schemas) belongs in `@owlmeans/viable`, not here. An application outside
12
+ the Viable platform has no use for it. The package's skills are `viable-common` and
13
+ `agent-presentation`.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ bun add @owlmeans/viable-common@^0.0.47
19
+ ```
10
20
 
11
21
  ## What is in it
12
22
 
13
23
  | Subpath | Contents |
14
24
  |---|---|
15
- | `.` | The shapes a generated project is described by: user stories and entities, the design and scaffold plans, UX/UI specs, the `docs/` metadata paths, the four user areas, the model roles and personas, moderation categories, slot metadata |
16
- | `@owlmeans/viable-common/slot` | The slot command vocabulary — file, shell and git commands, the sub-project roles, the target's ports and process markers |
25
+ | `.` | The shapes a generated project is described by: the planning module (Viable card types and flows), user stories and entities, the design and scaffold plans, UX/UI specs, the `docs/` metadata paths, the four user areas and the tenancy decision, model roles and personas, blueprint types, moderation categories, slot metadata, the agent-output presentation taxonomy. Re-exports every subpath except `./intent` |
26
+ | `@owlmeans/viable-common/slot` | The slot command vocabulary — file, shell, git and database commands, the sub-project roles and layouts, the target's ports and process markers |
17
27
  | `@owlmeans/viable-common/connect` | The connector protocol: sessions, operations, model tasks, questions, domain statuses, capabilities, the error family, and `connectProtocols()` — the one declaration both the platform and the SDK bind |
18
28
  | `@owlmeans/viable-common/convert` | Converting an application that already exists: the stages and their transitions, the origin and stack taxonomy, the census classifiers, and the `docs/conversion/` layout |
19
29
  | `@owlmeans/viable-common/integrity` | The target-shape manifest — what a slot is allowed to install, build and run — per target layout |
20
- | `@owlmeans/viable-common/legal` | `OWLMEANS_LEGAL_DATES`, `LegalDocumentDates` and `LegalDocumentKey` — shared ISO dates for the public site's policies and the platform's legal acceptance; no runtime dependencies |
30
+ | `@owlmeans/viable-common/intent` | The intent-first hand-off from the public site: `makeIntentProtocols`, `intentFlow`, the stash/pickup schemas, `IntentDraft`, `IntentExpired` / `IntentThrottled` |
31
+ | `@owlmeans/viable-common/iam-console` | The owner console's IAM contract shared by the browser and the connector: route params, closed bodies, answers, every `Iam*Schema`, `IAM_REFUSED` |
32
+ | `@owlmeans/viable-common/legal` | `OWLMEANS_LEGAL_DATES`, active `LegalDocumentDates`, `PendingLegalDocumentDates`, `LegalDocumentDateMetadata` and `LegalDocumentKey` — shared active ISO dates and explicit pending metadata; no runtime dependencies |
33
+
34
+ ## Concepts
35
+
36
+ - **Viable card** — a project, user story or specification is an `@owlmeans/planning` workcard of a
37
+ `VIABLE_*_TYPE`; what is Viable's lives under the card's `fields`, validated by
38
+ `ViableProjectFieldsSchema` / `ViableStoryFieldsSchema`.
39
+ - **Story code** — `US-` + five uppercase characters; the vocabulary of a target's files. A card id
40
+ never reaches a target file.
41
+ - **Area** — `ProjectArea`: guest `/`, user `/frontoffice`, admin `/admin`, operator `/backoffice`.
42
+ There is no fifth area.
43
+ - **Tenancy** — `ProjectTenancy` (`operators`, `users`), recorded on the project card and read only
44
+ through `tenancyHelper`.
45
+ - **Connector protocol** — the immutable HTTP tree `connectProtocols(opts)` declares; each runtime
46
+ binds its own materialization and injects only deployment parts (guard, gates, paid gates).
47
+ - **Target layout** — `TargetLayout`; the integrity manifest is per layout, and a legacy layout must
48
+ still verify clean.
49
+ - **Agent-output presentation** — `agentPresentationHelper.classifyAgentMessage` sorts a model message
50
+ into code, diff, structured, Markdown or plain, with a specialist role.
51
+
52
+ ## Usage
53
+
54
+ ### Bind the connector protocol tree
55
+
56
+ The tree is the same everywhere; the deployment supplies its guard and gates.
57
+
58
+ ```typescript
59
+ import { DEFAULT_GUARD } from '@owlmeans/auth-common'
60
+ import { ConnectPaidGate, connectProtocols } from '@owlmeans/viable-common/connect'
61
+
62
+ const tree = connectProtocols({
63
+ guard: DEFAULT_GUARD,
64
+ gate: { alias: 'project-owner', params: ['id'] },
65
+ accountGate: { alias: 'account-owner', params: [] },
66
+ paid: { [ConnectPaidGate.LocalLlm]: { alias: 'paid-llm', params: ['cap'] } },
67
+ })
68
+
69
+ tree.project.status // a protocol object — bind it in the server, call it from the SDK
70
+ tree.account.base // `/connect/account`, a root of its own beside `tree.base`
71
+ ```
21
72
 
22
- ## Installation
73
+ ### Read the cards and the tenancy decision
23
74
 
24
- ```bash
25
- bun add @owlmeans/viable-common@^0.0.46
75
+ ```typescript
76
+ import { ProjectArea, tenancyHelper, viableCardHelper } from '@owlmeans/viable-common'
77
+
78
+ if (viableCardHelper.isViableStory(card)) {
79
+ const { area, primary } = viableCardHelper.storyFieldsOf(card) // absent area reads as guest
80
+ const story = viableCardHelper.userStoryOf(card, design)
81
+ }
82
+
83
+ const tenancy = tenancyHelper.tenancyOf(blueprint) // NO_TENANCY unless a literal `true`
84
+ tenancyHelper.tenantedArea(ProjectArea.User, tenancy) // follows `users`
85
+ viableCardHelper.isUserChannel(scope.channel) // `web` / `connect` only
86
+ ```
87
+
88
+ ### Verify a target tree
89
+
90
+ The verifier does no IO: read every path in `TARGET_INTEGRITY_FILES` (`null` for an unreadable
91
+ one) and hand the map over.
92
+
93
+ ```typescript
94
+ import { TARGET_INTEGRITY_FILES, targetIntegrityHelper } from '@owlmeans/viable-common/integrity'
95
+
96
+ const files = Object.fromEntries(await Promise.all(
97
+ TARGET_INTEGRITY_FILES.map(async path => [path, await readOrNull(path)] as const)
98
+ ))
99
+ const report = targetIntegrityHelper.verifyTargetShape(files)
100
+ if (!report.ok) {
101
+ throw new Error(targetIntegrityHelper.formatIntegrityReport(report))
102
+ }
26
103
  ```
27
104
 
105
+ ### Classify agent output
106
+
107
+ ```typescript
108
+ import { AgentMessageCategory, agentPresentationHelper } from '@owlmeans/viable-common'
109
+
110
+ const input = { agent: 'coder', action: 'plan-scaffold', outputType: 'tool_calls', value: toolCall }
111
+ if (!agentPresentationHelper.isAgentMessageHidden(input)) {
112
+ const presentation = agentPresentationHelper.classifyAgentMessage(input)
113
+ if (presentation.category === AgentMessageCategory.Structured) {
114
+ renderCard(presentation.structure, presentation.role)
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Legal dates
120
+
121
+ ```typescript
122
+ import { OWLMEANS_LEGAL_DATES } from '@owlmeans/viable-common/legal'
123
+
124
+ const terms = OWLMEANS_LEGAL_DATES.terms // { effective, updated } ISO dates
125
+ const dpa = OWLMEANS_LEGAL_DATES['data-processing-agreement'] // { status: 'pending', effective: null, … }
126
+ ```
127
+
128
+ ## API
129
+
130
+ The full export list is the package's `src/` barrel; the groups an app reaches for:
131
+
132
+ | Area | Exports |
133
+ |---|---|
134
+ | Planning | `VIABLE_PROJECT_TYPE`, `VIABLE_STORY_TYPE`, `VIABLE_SPEC_TYPE`, `VIABLE_TYPE_SCHEMAS`, `VIABLE_FLOW_SCHEMAS`, `ViableStoryStatus`, `ViableProjectStatus`, `ViableChannel`, `ViableProjectCard`, `ViableStoryCard`, `viableCardHelper`, `viableSpecHelper`, `landingSentenceHelper` |
135
+ | Project refusals | `ProjectNotFound`, `ProjectPermissionError`, `ProjectStoryNotFound`, `ProjectStoryMissconfigured`, `ProjectAgentOccupied` and their bases |
136
+ | Areas and tenancy | `ProjectArea`, `AREA_PATHS`, `AREA_ACCESS`, `AREA_TIER`, `ADMIN_PERMISSION`, `OPERATOR_PERMISSION`, `ProjectTenancy`, `ViableTenancyDecision`, `NO_TENANCY`, `tenancyHelper`, `TENANCY_QUOTE_MAX` |
137
+ | Blueprint and skills | `Blueprint`, `BlueprintRef`, `BlueprintCase`, `GameKind`, `WorkKind`, `landingGatePreferenceOf`, `ViableSkill`, `ViablePersona` |
138
+ | Design and scaffold | `StoryDesign`, `ScaffoldPlan`, `ScaffoldPlanSchema`, `landingPlanHelper`, `StoryDesignPort`, `AccessBlock`, `PermissionDefault` |
139
+ | Slot metadata | `SlotMetadata`, `metadataConfigs`, `metadataLists`, `metadataSecrets`, `BRANDING_ENV_KEYS`, `brandingEnv` |
140
+ | Agent output | `agentPresentationHelper`, `AgentMessageCategory`, `AgentStructuredKind`, `AgentCodeLanguage`, `AgentMarkdownKind`, `AgentMessageRole` |
141
+ | `./slot` | `SlotCommandType`, `slotCommandHelper`, `SubProject`, `LAYOUTS`, `ROLE_DIRS`, `slotLayoutHelper`, `slotOriginHelper`, `DATABASE_READ_LIMITS` |
142
+ | `./connect` | `connectProtocols`, `connect`, `connectRef`, `ConnectEntrypointOptions`, `ConnectPaidGate`, `ModelTier`, `modelTierHelper`, the view and body types with their `*Schema`s, `CONNECT_CALL_*`, the `Connect*` error family |
143
+ | `./convert` | `ConversionStage`, `conversionStageHelper`, `OriginKind`, `StackId`, `censusHelper`, `conversionDocHelper`, `CENSUS_SKIP_DIRS`, `SOURCE_LIST_EXCLUSIONS` |
144
+ | `./integrity` | `TargetLayout`, `TARGET_LAYOUTS`, `targetLayoutHelper`, `targetIntegrityHelper`, `TARGET_INTEGRITY_FILES`, `TARGET_PROTECTED_FILES` |
145
+ | `./intent` | `intent`, `makeIntentProtocols`, `intentFlow`, `IntentStashBodySchema`, `IntentPickupBodySchema`, `IntentDraft`, `IntentExpired`, `IntentThrottled` |
146
+
147
+ ### Error statuses
148
+
149
+ | Status | Classes |
150
+ |---|---|
151
+ | 402 | `ConnectOutOfCredits` |
152
+ | 428 | `ConnectConsentRequired`, `ConnectConfirmationRequired` |
153
+ | 404 | `ProjectNotFound`, `ProjectStoryNotFound`, `ConnectSessionNotFound`, `ConnectOpUnknown` |
154
+ | 409 | `ProjectAgentOccupied`, `ProjectStoryMissconfigured`, `ConnectSessionGone`, `LocalSlotUnsupported` |
155
+ | 410 | `ConnectCallLost` |
156
+ | 422 | `ConnectOpRefused` |
157
+
28
158
  ## Rules worth knowing before you change something
29
159
 
30
160
  **A schema is written for the reader that will refuse it.** Model-answer schemas are annotated
@@ -39,18 +169,37 @@ provider's structured output writes an unset optional as `null`, and a wire body
39
169
  means "inherit" has no other spelling. `tests/convert.spec.ts` walks every exported schema for
40
170
  both faults, and for draft-04 tuple `items`.
41
171
 
42
- **A field that crosses a version skew carries no `enum`.** A connector is installed with
43
- `npx -y @owlmeans/viable-mcp@^0.1.18-rc.46` and talks to a separately deployed platform, so an executor kind it
44
- sends must remain an unused capability on an older platform rather than a refused session.
172
+ **A field that crosses a version skew carries no `enum`.** The Viable MCP connector is installed
173
+ from a moving `npx` range and talks to a separately deployed platform, so an executor kind it sends
174
+ must remain an unused capability on an older platform rather than a refused session.
45
175
 
46
176
  **A ceiling exists once.** The inquiry answer cap here equals `DEFAULT_INQUIRY_ANSWER_CHARS` in
47
177
  `@owlmeans/llm-common` and must stay equal; two ceilings mean the larger one truncates silently
48
178
  at the smaller.
49
179
 
50
- ## Related
51
-
52
- - `@owlmeans/viable-sdk` — the connector SDK written against these contracts
53
- - `@owlmeans/viable-mcp` — the npx MCP server built on that SDK
180
+ **A new connector route is declared here first**, then bound in every runtime that serves or calls
181
+ it — a route declared on one side alone is an unexplained 404.
182
+
183
+ ## Common pitfalls
184
+
185
+ - Importing `./intent` from the barrel — it is the one subpath the barrel does not re-export.
186
+ - Computing a conversion transition at a call site instead of `conversionStageHelper.stageAfter` /
187
+ `.canEnter`.
188
+ - Adding a required key to `SlotMetadata` — the publisher refuses a body with a key it does not
189
+ know, so new keys are optional and omitted while unset.
190
+ - Redeclaring a project refusal downstream — unmarshalling is by type name, last registration wins,
191
+ and `instanceof` breaks.
192
+ - Passing a card id into a target file instead of the story code.
193
+ - Putting agent-only data (skill bodies, case tables) here — it ships in every browser bundle.
194
+
195
+ ## Related packages
196
+
197
+ - [`@owlmeans/viable-sdk`](../viable-sdk) — the connector SDK written against these contracts
198
+ - [`@owlmeans/viable-log`](../viable-log) — target-side analytics and error plugins for the preview channel
199
+ - [`@owlmeans/planning`](../planning) — the workcard model the planning module builds on
200
+ - [`@owlmeans/agent-common`](../agent-common) — run and pipeline contracts
201
+ - [`@owlmeans/llm-common`](../llm-common) — `LlmPurpose`, the inquiry ceilings, spectator contracts
202
+ - [`@owlmeans/iam`](../iam) — the IAM vocabulary `./iam-console` re-exports
54
203
 
55
204
  <!-- owlmeans:agent-guidance:start -->
56
205
  ## Agent guidance
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/viable-common",
4
- "version": "0.0.46",
5
- "generatedAt": "2026-10-06T11:45:57.674Z",
4
+ "version": "0.0.47",
5
+ "generatedAt": "2026-10-08T08:16:20.564Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -6,7 +6,7 @@ description: Shared, runtime-free taxonomy for presenting OwlMeans Viable agent
6
6
 
7
7
  # Agent output presentation
8
8
 
9
- **Install:** `"@owlmeans/viable-common": "^0.0.46"` in `dependencies`
9
+ **Install:** `"@owlmeans/viable-common": "^0.0.47"` in `dependencies`
10
10
 
11
11
  `@owlmeans/viable-common`'s `agent/presentation.ts` owns the browser-safe vocabulary for agent
12
12
  output. Keep the server and every client on `agentPresentationHelper.classifyAgentMessage()`; consumers may refine a
@@ -8,8 +8,8 @@ user-invocable: false
8
8
  # @owlmeans/viable-common
9
9
 
10
10
  **Layer:** Cross-cutting domain (contracts only)
11
- **Install:** `"@owlmeans/viable-common": "^0.0.46"` in `dependencies`
12
- **Subpaths:** `.` · `./slot` · `./connect` · `./convert` · `./integrity` · `./intent` · `./legal` — the barrel
11
+ **Install:** `"@owlmeans/viable-common": "^0.0.47"` in `dependencies`
12
+ **Subpaths:** `.` · `./slot` · `./connect` · `./convert` · `./integrity` · `./intent` · `./legal` · `./iam-console` — the barrel
13
13
  re-exports every subpath except `./intent`.
14
14
  **Runtime-free:** no `@langchain/*`, no filesystem, no Ajv at run time (a devDependency, for the
15
15
  tests that compile the schemas); it depends on the packages under Depends On and nothing else.
@@ -33,11 +33,12 @@ execution state and card fields name.
33
33
  |---|---|
34
34
  | `.` (barrel) | The planning module (`VIABLE_*_TYPE`, `VIABLE_TYPE_SCHEMAS`, `VIABLE_FLOW_SCHEMAS`, `ViableStoryStatus`/`ViableProjectStatus` and their transitions, `ViableSpecCategory`, `ViableRelationship`, `ViableChannel`, `ViableProjectCard`/`ViableStoryCard`, the card helpers, the landing sentence helpers, the `Project*` refusals); `SlotMetadata` and the three metadata vocabularies (`metadataConfigs`, `metadataLists`, `metadataSecrets`), `BRANDING_ENV_KEYS` / `brandingEnv`; `ProjectArea` / `AREA_PATHS` / `AREA_ACCESS` / `AREA_TIER`, `ADMIN_PERMISSION` / `OPERATOR_PERMISSION`; the tenancy contract (`ProjectTenancy`, `ViableTenancyDecision`, `NO_TENANCY`, `tenancyHelper` (`tenancyOf`, `tenantedArea`), `TENANCY_QUOTE_MAX`); `ModelRole` and the viable `ExecutionState`; the `ViableSkill` / `ViablePersona` enums; the `Blueprint` layer types, `BlueprintRef` / `BlueprintPatch`, `BlueprintCase` / `GameKind` / `WorkKind`, `CASE_QUOTE_MAX`, `DEFAULT_BLUEPRINT_ID` / `BLUEPRINT_META_KEY`, `landingGatePreferenceOf`; the target topology (`TopologyDescriptor`, `LAYOUT_TOPOLOGIES`, `topologyHelper` (`resolveTopology`, `packageForRole`) — meaning in `/blueprints`); the BA shapes (`connectingStoryHelper.mergeConnectingStories`), the dev (`AccessBlock`, `AccessLevel`, `PermissionDefault`), UX, design and scaffold shapes and their schemas, `StoryDesignPort`; `ModerationCategory` / `ModerationSubject` / `moderationVerdictHelper.decideModeration`; the `docs/` metadata paths; `PreviewEventType` (error kinds plus `Analytics` — an analytics event a target's web posted through the preview reporter's channel; the target-side plugins live in `@owlmeans/viable-log`) and the `OwlMeansAnalyticsPayload` shape; the agent-output taxonomy (`agentPresentationHelper` — `classifyAgentMessage`, `isAgentMessageHidden`; `/agent-presentation`) and the spectator entry types |
35
35
  | `./slot` | `SlotCommandType` and the `SlotFileCommand` / `SlotShellCommand` / `SlotGitCommand` / `SlotDatabaseCommand` sets; `SlotDatabaseInfo`, `SlotDatabaseQueryArgs` / `SlotDatabaseQueryResult`, `DATABASE_READ_LIMITS`; the per-command deadlines and timeouts (`slotCommandHelper` — `commandDeadline`, `commandTimeout`), `SubProject`, `LAYOUTS` / `ROLE_DIRS` / `slotLayoutHelper.subprojectDirOf`, `WorkloadKind`, the target ports and process markers, `slotOriginHelper` (`slotOrigin` / `targetRedirectUrisForOrigin`) |
36
- | `./connect` | `ConnectTarget`, `ConnectLlm`, `ConnectHarness`, `ConnectExecutor`, `ConnectOpKind`, `ConnectProjectStatus`, `ConnectStoryStatus`, `ConnectPipelineState`, `ConnectWaitReason`, `ConnectProjectBranding` / `ConnectProjectBrandingSave`, the planning-kit views (`PlanningKitView`, `ConnectKitDescribe`, `ConnectKitApplyBody`, `ConnectKitApplyResult` and their `*Schema`s), `ModelTier` + `modelTierHelper` (`tierOfRole`/`clampTier`), `ModelTask*`, `InquiryPayload` + `ConnectInquiryKind`, the session and domain-status views, the convert bodies (`ConnectConvertCreateBody`, `ConnectConvertStartBody`, `ConnectConvertProceedBody`), the `Connect*` error family with `ConnectConfirmation` / `ConnectConfirmationAction`, `connectProtocols(opts)` and every `*Schema` behind them |
36
+ | `./connect` | `ConnectTarget`, `ConnectLlm`, `ConnectHarness`, `ConnectExecutor`, `ConnectOpKind`, `ConnectProjectStatus`, `ConnectStoryStatus`, `ConnectPipelineState`, `ConnectWaitReason`, `ConnectProjectBranding` / `ConnectProjectBrandingSave` / `ConnectProjectBrandingFields` / `ConnectBrandingCredit` / `ConnectBrandingCreditBody`, the configuration contract (`ConnectScopeQuery`, `ConnectConfigScope`, `ConnectProjectConfig`, `ConnectConfigVariable`, `ConnectFrontendVariable`, `ConnectConfigValue`, `ConnectConfigSaveBody`, `CONNECT_CONFIG_*`), the organization's defaults (`ConnectOrganizationBranding(Save)`, `ConnectBrandingBackfill`), the planning-kit views (`PlanningKitView`, `ConnectKitDescribe`, `ConnectKitApplyBody`, `ConnectKitApplyResult` and their `*Schema`s), `ModelTier` + `modelTierHelper` (`tierOfRole`/`clampTier`), `ModelTask*`, `InquiryPayload` + `ConnectInquiryKind`, the session and domain-status views, the convert bodies (`ConnectConvertCreateBody`, `ConnectConvertStartBody`, `ConnectConvertProceedBody` + `ConnectConvertProceedUpdate`), `ConnectAgentLock`, `ConnectPaidGate` + `ConnectGateRef` + `ConnectEntrypointOptions`, the call collection (`CONNECT_CALL_HEADER`, `CONNECT_CALL_ACCEPT_MS`, `CONNECT_CALL_COLLECT_WAIT_SEC`, `CONNECT_CALL_LOST_MS`, `ConnectCallState`, `ConnectCallPending`, `ConnectCallResult`, `ConnectCallCollectParams` / `ConnectCallCollectQuery` and their `*Schema`s), the `Connect*` error family with `ConnectConfirmation` / `ConnectConfirmationAction`, `connectProtocols(opts)` and every `*Schema` behind them |
37
37
  | `./convert` | `ConversionStage`/`Status`/`Decision` and the `conversionStageHelper` transitions (`stageAfter`/`decisionFor`/`canEnter`), `OriginKind`/`OriginShape`/`OriginState`, `StackId` + `STACK_FAMILY`, `ArchitectureCase`, `ConvertibilityVerdict`/`ConvertibilityReason`, the census classifiers (`censusHelper` — `fileClassOf`, `sizeClassOf`, `entropyClassOf`, `binaryByExtension`), the `docs/conversion/` paths, `CONVERTED_ORIGIN_DIR`, `SOURCE_LIST_EXCLUSIONS`, `CENSUS_SKIP_DIRS`, `RELOCATE_ALWAYS_KEEP`, and the model-answer schemas the conversion asks with |
38
38
  | `./integrity` | `TargetLayout` + `TARGET_LAYOUTS`, `targetLayoutHelper` (`detectTargetLayout`, `isLegacyLayout`, `targetPackageName`), `targetIntegrityHelper.verifyTargetShape`, `TARGET_INTEGRITY_FILES`, `TARGET_PROTECTED_FILES` |
39
39
  | `./intent` | `intent` (the four aliases), `makeIntentProtocols(opts?)`, `intentFlow` + `IntentFlowStep` + `INTENT_PAYLOAD_REF`, `IntentStashBodySchema` / `IntentPickupBodySchema`, the `INTENT_*` constants, `IntentDraft`, `IntentExpired` (404) / `IntentThrottled` (429) |
40
- | `./legal` | `OWLMEANS_LEGAL_DATES`, `LegalDocumentDates`, `LegalDocumentKey` — the public site's legal dates and the platform's legal acceptance dates |
40
+ | `./iam-console` | The owner console's IAM contract both doors share (the browser's `back.iam`, the connector's `connect.iam`): the route params (`IamProjectParams`, `IamProjectUserParams`, `IamOrganizationParams`, `IamMemberParams`, `IamGroupParams`), `IamScoped`, the bodies (`IamDefinitionUpdate`, `IamStaffSync`, `IamAssignGrant` / `IamRevokeGrant`, `IamGrantsQuery`, `IamProjectUserInvite` / `Update`, `IamOrganizationEdit`, `IamProjectMemberInvite` / `Update`, `IamGroupCreate` / `Edit`, `IamGroupMembersChange`), the answers (`IamListResponse` + `external`, `IamUsersResponse`, `IamPermissionsResponse` + `IamTenancy`, …, `IamStaffSyncResponse`), every `Iam*Schema` (with `IamScopedSchema`, `IamGroupRefSchema`), `IAM_REFUSED`, and the `@owlmeans/iam` vocabulary re-exported (`IamDefaultClass`, `IamGrantMode`, `IamGrantOrigin`, `IamRemovalPolicy`, `IAM_AREAS`, `IAM_MEMBERS_GROUP`, the record types). The refusal's CLASS (`IamRefused`, 409) is the platform's |
41
+ | `./legal` | `OWLMEANS_LEGAL_DATES`, `LegalDocumentDates`, `PendingLegalDocumentDates`, `LegalDocumentDateMetadata`, `LegalDocumentKey` — active dates and pending metadata for public legal sources and acceptance |
41
42
 
42
43
  ## Shared legal dates (`./legal`)
43
44
 
@@ -45,15 +46,23 @@ Import `OWLMEANS_LEGAL_DATES` from `@owlmeans/viable-common/legal` for legal-pag
45
46
  platform consent configuration. This subpath has no runtime imports; it loads only the date table.
46
47
  The package barrel also re-exports it. Never import another repository's sources by path.
47
48
 
48
- `src/legal/consts.ts` owns the ISO `YYYY-MM-DD` effective/updated dates; `src/legal/types.ts`
49
- declares `LegalDocumentDates` and the complete `LegalDocumentKey` union. A new document must add
50
- both a key and a table row; `satisfies Record<LegalDocumentKey, LegalDocumentDates>` checks coverage.
49
+ `src/legal/consts.ts` owns active ISO `YYYY-MM-DD` effective/updated dates and pending entries with
50
+ `status: 'pending'`, `effective: null`, `updated: null`. `src/legal/types.ts` declares active and
51
+ pending shapes, their `LegalDocumentDateMetadata` union, and the complete `LegalDocumentKey` union.
52
+ A new document must add both a key and a table row;
53
+ `satisfies Record<LegalDocumentKey, LegalDocumentDateMetadata>` checks coverage.
51
54
  Format dates in the consumer's locale, keeping policy text as placeholders rather than copied dates.
52
55
 
53
- Changing a terms/privacy/billing/product updated date changes the platform's terms-acceptance
54
- digest and requires acceptance again; privacy.updated also revises marketing consent.
55
- Cookies, services-agreement and platform-license dates are display-only. Rebuild this package
56
- before the platform and static-site consumers; both must receive the same table revision.
56
+ The Platform accepts `terms` and `platform-license` (combined subscription/billing), with privacy
57
+ disclosed separately; product-use rules live in Terms. `billing` and `product` preserve historical
58
+ acceptance dates as compatibility aliases. DPA (`data-processing-agreement`), subprocessor (`subprocessors`), company-notice
59
+ (`company-information`), acceptable-use (`acceptable-use`), refund (`refund-cancellation`) and
60
+ service-level (`service-level-agreement`) entries remain pending until coordinated release.
61
+ Render an explicit pending notice for a pending entry; never send null to a date formatter or
62
+ substitute a preparation date. Optional purposes carry independent wording revisions in the consuming
63
+ app, so editing privacy alone must not enlarge an existing grant. Legal-date activation is coordinated
64
+ with publication and the configured acceptance digest. Rebuild this package before the platform and
65
+ static-site consumers; both must receive the same table revision.
57
66
 
58
67
  ## The planning module
59
68
 
@@ -115,7 +124,7 @@ the wire and in target files — a parent agent's vocabulary, which never change
115
124
  | project `id` / story `id` | `id` (a card id) |
116
125
  | project `alias` / `name` / `description` | `code` / `title` / `description` |
117
126
  | project `specification` / `vision` / `designSystem` | specification bodies, categories `specification` / `vision` / `design-system` |
118
- | project `formerAliases`, `language`, `blueprint`, `blueprintCase`, `gameKind`, `workKind`, `caseQuote`, `target`, `origin`, `connectLlmMode`, `converterLlmMode` | `fields.*` |
127
+ | project `formerAliases`, `language`, `blueprint`, `blueprintCase`, `gameKind`, `workKind`, `caseQuote`, `target`, `origin`, `connectLlmMode` | `fields.*` |
119
128
  | the landing-gate decision | project `fields.landing` — `{ story: code \| null, at }` |
120
129
  | the tenancy decision | project `fields.tenancy` — `ViableTenancyDecision` `{ operators, users, quotes?, by: 'model' \| 'owner', at }` |
121
130
  | story narrative (`story`) / `code` / `status` | `title` / `code` / `status` (same strings) |
@@ -264,25 +273,53 @@ refused session. Apply this to what a newer connector may send an older platform
264
273
 
265
274
  `connectProtocols(opts)` is the connector's whole immutable HTTP tree — aliases, paths, methods,
266
275
  contracts, parents. The platform and the SDK bind their own materializations of it; only the
267
- DEPLOYMENT's parts are injected: the guard alias, the ownership gate, and the paid local-LLM gate
268
- (on `session.openDelegated` alone). One base (`/connect` unless `path` says otherwise); `connect`
269
- (aliases) and `connectRef` (typed references) name the same set:
276
+ DEPLOYMENT's parts are injected (`ConnectEntrypointOptions`): the guard alias, the ownership `gate`,
277
+ the `accountGate` and the `paid` map — `Partial<Record<ConnectPaidGate, ConnectGateRef>>`, the gate
278
+ of each kind of spend (`LocalLlm`, `Whitelabel`, `CustomDomain`, `ProductionStandalone`,
279
+ `PublishedSites`). A route declares its KIND (`paidGate(kind)` inside the factory); the deployment
280
+ names the gate service and parameters, so a connector route carries exactly its browser twin's gate.
281
+ `localLlm` is the deprecated alias of `paid[LocalLlm]`, read only when the map names none. Two roots:
282
+ `base` (`/connect` unless `path` says otherwise, the ownership gate) and `account.base`
283
+ (`<path>/account`, the account gate) — a root of its own, never a child of `base`, because
284
+ `getGates()` keeps one gate per service and the two ownership gates share one. `connect` (aliases)
285
+ and `connectRef` (typed references) name the same set, the two bases aside:
270
286
 
271
287
  | Branch | Routes |
272
288
  |---|---|
289
+ | `account` | `base` — the organization's and the person's own records, the account gate inherited; `branding.get` GET / `.save` POST `/branding` (`ConnectOrganizationBranding { organizationName, copyright }`, the save a PATCH `ConnectOrganizationBrandingSave`), `branding.backfill` POST `/branding/backfill` → `ConnectBrandingBackfill { projects }`; `llm.get` GET / `llm.set` POST `/llm` (`ConnectLlmBody` → `ConnectProfileSettingsView { llmMode, canUseLocal }`, the set the `LocalLlm` paid gate); `tokens.list` GET `/access-tokens` → `ConnectAccessTokenList` (`ConnectAccessToken` — no secret, no hash, no owner ids, `oauth`), `tokens.revoke` POST `/access-tokens/:id/revoke` (`ConnectAccessTokenParams` ≤ `CONNECT_TOKEN_ID_MAX`) → `ConnectAccessTokenRevoked` — NO create, and never under `/tokens`; `privacy.status` GET `/privacy` → `ConnectPrivacyChoices { pending, items: ConnectPrivacyChoice[] }` (`granted` = the SAVED answer), `privacy.withdraw` POST `/privacy/withdraw` (`ConnectPrivacyWithdrawBody { keys }`, 1–`CONNECT_PRIVACY_KEYS_MAX` unique keys ≤ `CONNECT_PRIVACY_KEY_MAX`, no field a grant could travel in) — NO grant or terms; `intent.pickup` POST `/intent/pickup` (`ConnectIntentPickupBody { ref }`, the guest pickup's ref shape) → `ConnectIntentPickup { prompt }`; `iam.users` GET `/iam/users` → `IamUsersResponse` — every end user of every app the organization owns, read-only; `notifications` GET `/notifications` (`ConnectFeedQuery`) → `ConnectFeedPage` — the organization's notices |
273
290
  | `session` | `open` POST `/session`, `openDelegated` POST `/session/delegated`, `close` POST `/session/:sessionId/close` |
274
291
  | `op` | `pull` GET `/session/:sessionId/ops` (the long poll), `submit` POST `/session/:sessionId/ops/:opId` |
275
- | `project` | `create` POST / `list` GET `/project`, `attach` POST `/project/attach`, `confirm`, `status`, `reinit`, `modify` under `/project/:id/…`, `branding.get` GET / `.save` POST `/project/:id/branding`, `kit.describe` GET / `kit.apply` POST `/project/:id/kits` |
292
+ | `project` | `create` POST / `list` GET `/project`, `attach` POST `/project/attach`, `confirm`, `status`, `reinit`, `modify`, `rename` (`ConnectRenameBody { name, description? }` — the name, brief and code, never the address) under `/project/:id/…`, `branding.get` GET / `.save` POST `/project/:id/branding`, `branding.credit` POST `/project/:id/branding/credit` (`ConnectBrandingCreditBody { hideCredit }`, the `Whitelabel` paid gate), `branding.copyDefaults` POST `/project/:id/branding/copy-defaults` — all four with `?scope=` (`ConnectScopeQuery`), `kit.describe` GET / `kit.apply` POST `/project/:id/kits`, `destroy` DELETE `/project/:id` → `ConnectProjectSummary`, `unlock` POST `/project/:id/unlock` → `ConnectAgentLock { locked, task?, lockedAt? }` (also `ConnectProjectStatus.agent`) — both ownership only, `llm.get` GET / `llm.set` POST `/project/:id/llm` (`ConnectProjectLlmBody { llmMode: ConnectLlm \| null }` — `null` inherits — → `ConnectProjectSettings { llmMode, effective, canUseLocal }`, the set the `LocalLlm` paid gate); `activity` GET `/project/:id/activity` (`ConnectActivityQuery` — a feed query + `detail`) → `ConnectFeedPage` |
293
+ | `config` | `get` GET / `save` POST `/project/:id/config` (`?scope=`; the save `ConnectConfigSaveBody { backend?, frontend? }` — lists of `ConnectConfigValue { name, value }`, a name matching `CONNECT_CONFIG_NAME_PATTERN` ≤ `CONNECT_CONFIG_NAME_MAX`, a value ≤ `CONNECT_CONFIG_VALUE_MAX`, ≤ `CONNECT_CONFIG_SAVE_MAX` per side), `recollect` POST `/project/:id/config/recollect` → `ConnectProjectConfig { scope, backend: ConnectConfigVariable[], frontend: ConnectFrontendVariable[] }` — ownership only |
276
294
  | `story` | `status` GET `/project/:id/story/:storyId/status` |
277
- | `files` | `list` GET `/project/:id/files` |
295
+ | `files` | `list` GET `/project/:id/files`; `get` GET / `save` POST / `remove` DELETE `/project/:id/files/content` (`ConnectFileQuery { path }` ≤ `CONNECT_FILE_PATH_MAX` in the query; the save body `ConnectFileSaveBody { path, content }` — the whole file) → `ConnectFileContent { path, content }` / `ConnectFileWritten { path, buildWarning? }`; `meta` GET `/project/:id/files/meta` (`ConnectFileMetaQuery { kind: MetadataListKind, category?: SpecCategory }`, the category a nullable enum carrying `null`) → `string[]` — ownership only; `changes` GET `/project/:id/files/changes` (`ConnectFeedQuery`) → `ConnectFileChanges` (a feed page + `watching`) |
296
+ | `sandbox` | `run`, `restart`, `stop`, `rebuild` POST `/project/:id/sandbox/<verb>` → `ConnectSlotView` — the PREVIEW workload, ownership only |
297
+ | `slot` | `list` GET `/slot` → `ConnectSlotView[]` — the organization's workloads, ownership only |
298
+ | `git` | `status` GET `/project/:id/git` → `ConnectGitState { connection: ConnectGithubConnection \| null, git: ConnectGitStatus \| null }`; `log` GET `/project/:id/git/log` → `ConnectGitCommit[]`; `commit` POST `…/git/commit` (`ConnectGitCommitBody { message }` ≤ `CONNECT_GIT_MESSAGE_MAX`) → `ConnectGitCommitResult`; `discard` POST `…/git/discard` → `ConnectGitStatus`; `revert` POST `…/git/revert` (`ConnectGitRevertBody { hash }`, `CONNECT_GIT_HASH_PATTERN`) → `ConnectGitRevertResult { commit, dbWarning? }` — ownership only |
299
+ | `github` | `authorize` POST `/project/:id/github/authorize` → `ConnectGithubAuthorize { authorizeUrl }` (the address the PERSON opens — NO completion route exists); `publish` POST `…/github/publish` (`ConnectGithubPublishBody { repoName?, private?, existing?: { owner, repo } }`) → `ConnectGithubConnection`; `push` / `pull` POST → `ConnectGitSyncResult`; `disconnect` POST → `{ connection: null }`; `repos` GET `…/github/repos` (`ConnectGithubRepoQuery { page?, search? }`) → `ConnectGithubRepoList`; `branches` GET `…/github/branches` (`ConnectGithubBranchQuery { owner, repo, page? }`) → `ConnectGithubBranchList`; `link` POST `…/github/link` (`ConnectGithubLinkBody { owner, repo, branch? }`) → `ConnectGithubLinked` — ownership only; names ≤ `CONNECT_GITHUB_NAME_MAX`, branch ≤ `CONNECT_GITHUB_BRANCH_MAX`, page ≤ `CONNECT_GITHUB_PAGE_MAX`, search ≤ `CONNECT_GITHUB_SEARCH_MAX` |
300
+ | `production` | `status` GET `/project/:id/production` → `ConnectProductionStatus { workload: ConnectSlotState \| null, domain: ConnectProductionDomain \| null }`; `publish` (the `PublishedSites` paid gate — a LIMIT gate), `restart`, `stop` POST `…/production/<verb>` → `ConnectProductionStatus`; `domain.attach` POST `…/production/domain/attach` (`ConnectProductionDomainBody { domain }` — `CONNECT_DOMAIN_MIN`…`CONNECT_DOMAIN_MAX`, `CONNECT_DOMAIN_PATTERN`; the `CustomDomain` paid gate), `domain.verify` / `domain.detach` POST → `ConnectProductionDomain \| null`; `auth.get` GET `…/production/auth` → `ConnectProductionAuth { clientId, issuerUrl, secretSet, redirectUris, generatedHost, customDomain? }` and `auth.redirects` POST `…/production/auth/redirects` (`ConnectProductionRedirectsBody { redirects }` — ≤ `CONNECT_REDIRECTS_MAX` addresses of ≤ `CONNECT_REDIRECT_URI_MAX`) → `ConnectProductionRedirects { redirectUris }`, both the `ProductionStandalone` paid gate. The production workload, never the preview; NO `run` verb (a stopped site comes back by `restart`) and NO secret or reveal anywhere |
301
+ | `iam` | The generated app's sign-in, the owner console's twins under `/project/:id/iam` — ownership only, NO paid kind: `permissions` GET `…/permissions` (`ConnectScopeQuery`) → `IamPermissionsResponse`, `defaultUpdate` POST `…/permissions/default` (`IamDefinitionUpdate`); `grants.list` GET `…/grants` (`IamGrantsQuery`), `.assign` POST `…/grants`, `.revoke` POST `…/grants/revoke` (`IamAssignGrant` / `IamRevokeGrant` — one subject); `users.list` GET / `.invite` POST `…/users`, `.update` POST `…/users/:profileId`, `.remove` POST `…/users/:profileId/remove` (`IamScoped` body); `organizations.list` GET `…/organizations`, `.update` POST `…/organizations/:entitySlug`, `.members` GET / `.addMember` POST `…/:entitySlug/members`, `.updateMember` POST `…/members/:profileId`, `.removeMember` POST `…/members/:profileId/remove`; `groups.list` GET / `.ensure` POST `…/:entitySlug/groups`, `.update` POST `…/groups/:group`, `.remove` POST `…/groups/:group/remove`, `.members` GET / `.addMembers` POST `…/groups/:group/members`, `.removeMembers` POST `…/members/remove`. Params `ConnectIam{User,Organization,Member,Group}Params` (`id` = the project). Every write a POST with `scope` in its body; every read `scope` in the query; NO staff-sync twin |
278
302
  | `convert` | `create` POST `/convert`, `check` GET `/convert/:id/check`, `start`, `proceed`, `purge` POST `/convert/:id/…`, `status` GET `/convert/:id` |
279
303
  | `inquiry` | `answer` POST `/project/:id/inquiry/:inquiryId` |
280
304
  | `pipeline` | `state` GET `/pipeline/:id/:runId`, `resume` POST `/pipeline/:id/:runId/resume` |
281
-
282
- - No socket, capability view, session read, heartbeat, conversion cancel or inference-settings
283
- route exists. A project's inference modes are set by the browser through the platform's own API;
284
- `ConnectProjectSettings`, `ConnectProjectLlmBody(Schema)`, `ConverterProjectLlmBody(Schema)` stay
285
- here as that API's shapes.
305
+ | `call` | `collect` GET `/call/:callId` (query `wait` ≤ `CONNECT_CALL_COLLECT_WAIT_SEC`) → `ConnectCallResult` — under `base` (guard + ownership gate), never the paid gate |
306
+
307
+ - No socket, capability view, session read, heartbeat, conversion cancel, token create, consent
308
+ grant or terms route exists. A project has ONE inference setting — the person's preference
309
+ (`account.llm`) and a project override (`project.llm`, `null` inherits) — read and written through
310
+ the same shapes (`ConnectProfileSettings(View)`, `ConnectProjectSettings`, `ConnectLlmBody`,
311
+ `ConnectProjectLlmBody(Schema)`) by the browser's API and the connector alike; both writes carry
312
+ the `LocalLlm` paid gate. The setting is a DEFAULT (the browser's, a URL-configured host's): a stdio
313
+ connector's own `llm` is what its session attached with. A conversion carries no mode of
314
+ its own: like every run it follows the session that drives it, and `ViableProjectFieldsSchema`
315
+ refuses any other inference key on a card.
316
+ - Who performs the model calls is the connector's `llm` and nothing else: `ConnectExecutor.Model`
317
+ is advertised exactly when it is `local` (every model call is then the parent's), never in the
318
+ cloud mode; `Human` is advertised always.
319
+ - `project.create` (`ConnectCreateBody`) and `convert.create` (`ConnectConvertCreateBody`) carry
320
+ `sessionId?` — the caller's UNATTACHED delegated session; its pre-card checks are performed by
321
+ that session's parent, and absent the platform performs them. A nullable id like every other
322
+ (`{ ...idValue, nullable: true }`), and both bodies stay `additionalProperties: false`.
286
323
  - A new route is added here first (alias, declaration, `connectRef` entry), then bound in every
287
324
  runtime that serves or calls it — a route declared on one side alone is an unexplained 404. Raw
288
325
  aliases stay private to declaration modules; consumers receive protocol objects.
@@ -295,10 +332,60 @@ DEPLOYMENT's parts are injected: the guard alias, the ownership gate, and the pa
295
332
  — the start's whole body — and `ConnectConvertProceedBody(Schema)`): a PERSON agreed to what the
296
333
  step costs. The platform refuses a step that would use the plan's conversion or spend credits
297
334
  without it (`ConnectConfirmationRequired`); a `null` is "not confirmed", never a refused body.
298
- - Branding routes hang under `base` (guard + ownership gate, no paid gate). The save body
299
- (`ConnectProjectBrandingSaveSchema`) is a PATCH of strings with structural bounds only
300
- (`CONNECT_BRANDING_*_MAX`, each equal to its platform twin); value acceptability is the
301
- platform's rule on the MERGED record. The platform credit is a paid capability with its own route.
335
+ The proceed body also carries `update?: ConnectConvertProceedUpdate` — `name`, `description`,
336
+ `specification`, `vision`, `designSystem`, closed, never the alias — the person's edits to what
337
+ the analysis drafted, which the platform accepts only with the decision that starts the extraction.
338
+ - **A workload crosses the wire as a projection.** `ConnectSlotState` (`id`, `kind`, `status`,
339
+ `slug`, `host?`, `initialized?`, `lastError?`, `buildWarning?`, `backendWarning?` — `kind` and
340
+ `status` plain strings for the version skew) is `ConnectProjectStatus.slot`; `ConnectSlotView` adds
341
+ `projectId?` for the sandbox answers and the workload list. Never a namespace, workload, volume or
342
+ key: those are the deployment's infrastructure names.
343
+ - Branding routes hang under `base` (guard + ownership gate). The save body
344
+ (`ConnectProjectBrandingSaveSchema`) is a PATCH of the text fields (`ConnectProjectBrandingFields`)
345
+ with structural bounds only (`CONNECT_BRANDING_*_MAX`, each equal to its platform twin); value
346
+ acceptability is the platform's rule on the MERGED record. The platform credit is READ-ONLY on
347
+ `ConnectProjectBranding.credit` (`ConnectBrandingCredit { hidden, requested, entitled }`, optional
348
+ for a platform that predates it) and changes only through `branding.credit`, a project route
349
+ declaring a paid kind (`Whitelabel`), beside `session.openDelegated`, the two preference writes and
350
+ the production routes.
351
+ - **Git crosses as self-contained mirrors** (`connect/git/types.ts`): the same fields as the
352
+ platform's `@owlmeans/git/model` and `GithubConnection`, no git dependency here, every status a
353
+ plain string (version skew). NO shape carries the GitHub token, and no body has a field one could
354
+ travel in (`additionalProperties: false`).
355
+ - **Production crosses as projections** (`connect/production/types.ts`): the workload as the slot
356
+ state, the domain with its two DNS records (`customDomain` → `cnameTarget`, `dcvName` → `dcvValue`)
357
+ and the provider's raw states, every status a plain string. The production sign-in's client secret
358
+ has NO field: `ConnectProductionAuth.secretSet` says whether one exists. Each paid route declares
359
+ its kind (`PublishedSites`, `CustomDomain`, `ProductionStandalone`), so every paid kind is in use.
360
+ - **The owner console's IAM is ONE contract for both doors** (`./iam-console`, re-exported by the
361
+ barrel): the browser's `back.iam` routes and the connector's `connect.iam` twins validate the SAME
362
+ body schemas, so a field cannot be admitted by one and refused by the other. Every object is closed —
363
+ an organization travels by `entitySlug`, a group by key, never a record id; a grant names exactly one
364
+ subject (`OneSubject`); its nullable enums carry `null`. `IamRefused` stays the platform's class; the
365
+ marker it writes (`IAM_REFUSED`) is declared here.
366
+ - **The browser's sockets are cursor feeds here** (`connect/feed/types.ts`): `ConnectFeedRecord`
367
+ (`kind: ConnectFeedKind`, `at`, `run?`, `projectId?`, `storyId?`, `slotId?`, `action?`, `agent?`,
368
+ bounded `text?`, small `data?`) — a projection, never the record behind it; `ConnectFeedEntry` adds its
369
+ `id`; `ConnectFeedPage { cursor, entries, gap }`. A cursor is a stream id
370
+ (`CONNECT_FEED_CURSOR_PATTERN`, ≤ `CONNECT_FEED_CURSOR_MAX`; `CONNECT_FEED_START` = `0-0`), a page
371
+ ≤ `CONNECT_FEED_LIMIT_MAX` (default `CONNECT_FEED_LIMIT_DEFAULT`), a hold ≤ `CONNECT_FEED_WAIT_MAX_SEC`
372
+ (20 s). `ConnectFeedDetail` (`progress` | `thinking`) is a nullable enum carrying `null`. The three
373
+ feed routes are GETs with no paid kind — the tree still declares NO socket.
374
+ - `ConnectScopeQuery` (`ConnectScopeQuerySchema`) names `ephemeral` (the default — the preview's set)
375
+ or `production` (its own set, taken at a Publish) — a nullable enum carrying `null`, never `local`.
376
+ - **A backend variable's VALUE never crosses the connector.** `ConnectConfigVariable` is `{ name, set }`
377
+ only; a frontend variable (`ConnectFrontendVariable`) adds its public `value` — it is baked into the
378
+ bundle every visitor loads.
379
+ - **Request now, collect later.** In the delegated mode a write may wait on a model call the
380
+ connector's own parent performs, longer than an edge holds a response. The connector names every
381
+ non-GET request with `CONNECT_CALL_HEADER` (`x-viable-call`, a UUID it generated and reuses on a
382
+ retry); the platform holds a named call `CONNECT_CALL_ACCEPT_MS` (20 s), then answers 202
383
+ (`EntrypointOutcome.Accepted`) with `ConnectCallPending { pending: <id> }`; `call.collect` holds up
384
+ to `CONNECT_CALL_COLLECT_WAIT_SEC` (25 s) per poll and answers `ConnectCallResult { state, outcome?,
385
+ value?, error? }` — `settled` carries the value the call would have answered with (the empty schema
386
+ `{}`, never `nullable` without a type) or `error`, the call's failure as `ResilientError.marshal`
387
+ writes it; a pending call whose heartbeat is older than `CONNECT_CALL_LOST_MS` (90 s) is `lost`.
388
+ The collection is transport, not domain: no `ConnectorApi` member and no generic job endpoint.
302
389
  - Long work is read through its domain view — `ConnectProjectStatus`, `ConnectStoryStatus`,
303
390
  `ConversionStatusView`, `ConnectPipelineState` — each composing its record, run, pending inquiry
304
391
  and `waitingFor` reason; none exposes a generic operation id. A new long-running domain extends
@@ -436,7 +523,8 @@ silently at the smaller; never introduce a local cap.
436
523
  ## Errors: declared here, phrased where they are read
437
524
 
438
525
  `ConnectError` and its family (`ConnectSessionNotFound`, `ConnectSessionGone`, `ConnectOpTimeout`,
439
- `ConnectOpRefused`, `LocalSlotUnsupported`, `ConnectOpUnknown`, `ConnectOutOfCredits`,
526
+ `ConnectOpRefused`, `LocalSlotUnsupported`, `ConnectOpUnknown`, `ConnectCallLost` (`call-lost:<callId>`
527
+ — a collected call's outcome was never recorded), `ConnectOutOfCredits`,
440
528
  `ConnectConsentRequired`, `ConnectConfirmationRequired`) are `ResilientError` classes with
441
529
  `viable-connect:` markers. The three refusals a connector phrases for a person pack their fields
442
530
  into the message (only `type` and `message` survive a marshal), are built with `static encode(...)`
@@ -475,6 +563,7 @@ refuses an exported class whose status was not decided:
475
563
  | 428 | `ConnectConsentRequired`, `ConnectConfirmationRequired` |
476
564
  | 404 | `ProjectNotFound`, `ProjectStoryNotFound`, `ConnectSessionNotFound`, `ConnectOpUnknown` |
477
565
  | 409 | `ProjectAgentOccupied`, `ProjectStoryMissconfigured`, `ConnectSessionGone` (no connector attached), `LocalSlotUnsupported` |
566
+ | 410 | `ConnectCallLost` (the outcome is gone, not late) |
478
567
  | 422 | `ConnectOpRefused` |
479
568
  | none (500) | the bases, `ConnectOpTimeout` (a peer's fault), `ProjectPermissionError` (never thrown; a permission refusal extends `AuthForbidden`) |
480
569
 
@@ -488,12 +577,13 @@ the manager's `useErrorPhrase` read the same substrings. A marker change changes
488
577
 
489
578
  | File | Pins |
490
579
  |---|---|
491
- | `planning.spec.ts` | the two flows and transition tables, type declarations, slots, code policies, reserved types outside `cardTypes`, field schemas (null optionals, refused strays and closed-set values), landing fields and sentence, the tenancy decision, the work kind and bounded case quote, card helpers, the `follows` anchor, refusal type names after a marshal |
580
+ | `planning.spec.ts` | the two flows and transition tables, type declarations, slots, code policies, reserved types outside `cardTypes`, field schemas (null optionals, refused strays and closed-set values, no `converterLlmMode`), landing fields and sentence, the tenancy decision, the work kind and bounded case quote, card helpers, the `follows` anchor, refusal type names after a marshal |
492
581
  | `tenancy.spec.ts` | `NO_TENANCY` frozen, `tenancyHelper.tenancyOf` defaults and the literal-`true` rule, `.tenantedArea` |
493
582
  | `access-schema.spec.ts` | the model-facing access schema: model keys only, byte-identical |
494
583
  | `scaffold.spec.ts` | old- and new-shape plans passing the schema and slot, `null` optionals, no `minItems`, closed anchors/slots, the landing helpers |
495
584
  | `blueprint.spec.ts` · `branding.spec.ts` | `landingGatePreferenceOf` defaults · the build env and metadata vocabulary |
496
- | `connect-entrypoints.spec.ts` · `connect-convert.spec.ts` | every route's method and path, aliases = `connectRef`, the paid gate on the delegated session alone, no socket or story route, branding body, the kit routes and their closed shapes · conversion routes, the start's body and both verbs' `confirm`, an unknown executor kind accepted |
585
+ | `connect-entrypoints.spec.ts` · `connect-convert.spec.ts` | every route's method and path, aliases = `connectRef`, the paid kinds on the delegated session, the two preference writes and the credit switch alone, the account inference/token/privacy/intent routes and their closed bodies, the configuration routes and their closed bodies, the git and GitHub routes under the base with no paid gate and no completion route and their closed bodies, the production routes under the base each with its own paid kind, no secret or run verb, and their closed bodies, the IAM routes' count and addresses, the scope query, the account branding routes, no socket or story route, the create body's `sessionId`, branding body, the kit routes and their closed shapes, the collect route under the base and its timing constants, the pending/params/query/result shapes, the three feed routes (owned base / account base, GET, no paid gate, no socket) and the feed query shapes · conversion routes, the create body's `sessionId`, the start's body and both verbs' `confirm`, an unknown executor kind accepted |
586
+ | `iam-console.spec.ts` | the owner-console schemas (one subject, closed bodies, `null` in nullable enums), the 22 `connect.iam` routes under the base with no paid gate, the customer-wide listing under the account base, POST writes with `scope` in the body and reads with it in the query, the connector's IAM params |
497
587
  | `convert.spec.ts` | the three structural walks over the barrel, nullable enums under Ajv, census classifiers, stage transitions |
498
588
  | `design.spec.ts` | the design aggregate, staleness ranking, schema refusals, `storyDesignHelper.userStoryOfDesign` |
499
589
  | `error-status.spec.ts` · `connect-errors.spec.ts` | declared statuses through a marshal · packed refusal fields fresh and after a round trip, the confirmation's `decode` |
@@ -506,6 +596,8 @@ the manager's `useErrorPhrase` read the same substrings. A marker change changes
506
596
  - `@owlmeans/resource` — the `ResourceError` base of the project refusals
507
597
  - `@owlmeans/entrypoint`, `@owlmeans/route` — the entrypoint declarations
508
598
  - `@owlmeans/error` — the `Connect*` error family
599
+ - `@owlmeans/iam` — the owner console's IAM vocabulary `./iam-console` re-exports (public, runtime-light:
600
+ `auth`, `context`, `entrypoint`, `error`, `oidc`, `route`); `@owlmeans/auth-common` — `ENTITY_SLUG_PATTERN`
509
601
  - `@owlmeans/llm-common` — `ExecutionEffort`/`ExecutionLevel`, `LlmPurpose`, the spectator
510
602
  contracts, and the inquiry ceilings this package's copies are pinned to
511
603
  - `@owlmeans/agent-common` — the run and pipeline contracts (re-exported `AgentRunStatus`)
@@ -514,7 +606,7 @@ the manager's `useErrorPhrase` read the same substrings. A marker change changes
514
606
 
515
607
  ## Related
516
608
 
517
- - [[viable-sdk]] · [[viable-mcp]] — the connector SDK written against these contracts, and its npx
609
+ - [[viable-sdk]] · `@owlmeans/viable-mcp` (closed-source) — the connector SDK written against these contracts, and its npx
518
610
  stdio server
519
611
  - [[flow]] · [[client-flow]] — the model `intentFlow` is walked with, and `flowLandingOf(context).suspendFlow`
520
612
  - [[inquiry]] · [[llm-common]] — the primitive `InquiryPayload` mirrors; the model runtime's contracts
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The organization's branding defaults: the name and copyright line every new project starts with.
3
+ * A project keeps its own copy after creation; `copyDefaults` replaces a project's two values with
4
+ * these again.
5
+ */
6
+ export interface ConnectOrganizationBranding {
7
+ organizationName: string;
8
+ copyright: string;
9
+ }
10
+ /** A PATCH of the organization's defaults; a field left out keeps its value. Neither may be empty. */
11
+ export interface ConnectOrganizationBrandingSave extends Partial<ConnectOrganizationBranding> {
12
+ }
13
+ /** What a backfill did: how many projects had blank branding rows filled from the defaults. */
14
+ export interface ConnectBrandingBackfill {
15
+ projects: number;
16
+ }
17
+ /**
18
+ * One of the person's access tokens, as a connector sees it — never the secret, never its hash, and
19
+ * no record ids of the organization or the person: the token is the caller's own by construction.
20
+ */
21
+ export interface ConnectAccessToken {
22
+ id: string;
23
+ /** What the owner called it. */
24
+ name: string;
25
+ /** The prefix and the first characters of the secret — useless as a credential. */
26
+ display: string;
27
+ scopes: string[];
28
+ createdAt: string;
29
+ lastUsedAt?: string;
30
+ expiresAt?: string;
31
+ /** Set once a token is revoked; a revoked token stays listed so its name still resolves. */
32
+ revokedAt?: string;
33
+ /** Issued through a browser sign-in (an OAuth grant) for one resource, rather than minted by hand. */
34
+ oauth: boolean;
35
+ }
36
+ export interface ConnectAccessTokenList {
37
+ items: ConnectAccessToken[];
38
+ }
39
+ /** The token a revoke names — one of the caller's own. */
40
+ export interface ConnectAccessTokenParams {
41
+ id: string;
42
+ }
43
+ /** What a revoke answers: the id it revoked. Revoking twice is what a retry looks like. */
44
+ export interface ConnectAccessTokenRevoked {
45
+ id: string;
46
+ }
47
+ /** Whether a consent was ever answered at its current wording. */
48
+ export type ConnectPrivacyStatus = 'new' | 'revised' | 'current';
49
+ /** One marketing consent of the person, as the "Privacy choices" settings show it. */
50
+ export interface ConnectPrivacyChoice {
51
+ /** The consent's key — `marketing.email`, `data.profiling`, … */
52
+ key: string;
53
+ group: string;
54
+ mode: 'opt-in' | 'opt-out';
55
+ /**
56
+ * The person's SAVED, current answer — `false` for anything never answered at this wording,
57
+ * whatever the settings screen's opt-out display default says.
58
+ */
59
+ granted: boolean;
60
+ status: ConnectPrivacyStatus;
61
+ /** When the saved answer was given, if there is one. */
62
+ decidedAt?: string;
63
+ }
64
+ export interface ConnectPrivacyChoices {
65
+ /** A consent still waits for the person's first or revised answer. */
66
+ pending: boolean;
67
+ items: ConnectPrivacyChoice[];
68
+ }
69
+ /** The consents to withdraw — each written `granted: false`; nothing here can grant one. */
70
+ export interface ConnectPrivacyWithdrawBody {
71
+ keys: string[];
72
+ }
73
+ /** The reference of a stashed prompt — the `ref` of the `/start?ref=…` address the public site opened. */
74
+ export interface ConnectIntentPickupBody {
75
+ ref: string;
76
+ }
77
+ /** The prompt a visitor typed on the public site. Collected once: the reference is spent. */
78
+ export interface ConnectIntentPickup {
79
+ prompt: string;
80
+ }
81
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/connect/account/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,gBAAgB,EAAE,MAAM,CAAA;IACxB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,sGAAsG;AACtG,MAAM,WAAW,+BAAgC,SAAQ,OAAO,CAAC,2BAA2B,CAAC;CAAG;AAEhG,+FAA+F;AAC/F,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sGAAsG;IACtG,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,kBAAkB,EAAE,CAAA;CAC5B;AAED,0DAA0D;AAC1D,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAA;CACX;AAED,2FAA2F;AAC3F,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAA;CACX;AAED,kEAAkE;AAClE,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAA;AAEhE,sFAAsF;AACtF,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;IAC1B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,oBAAoB,CAAA;IAC5B,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,oBAAoB,EAAE,CAAA;CAC9B;AAED,4FAA4F;AAC5F,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAED,0GAA0G;AAC1G,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,6FAA6F;AAC7F,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAA;CACf"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/connect/account/types.ts"],"names":[],"mappings":""}