@opengeni/runtime 3.0.1 → 4.0.0-canary.35585322809001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/codemode-client.json +1 -0
- package/dist/chunk-4A4XTKKX.js +1 -0
- package/dist/{chunk-RIJ6DCYS.js → chunk-HCGLD7NH.js} +9817 -9494
- package/dist/chunk-HCGLD7NH.js.map +1 -0
- package/dist/{chunk-FHGLYLBL.js → chunk-SPT3PLMX.js} +1 -87
- package/dist/chunk-SPT3PLMX.js.map +1 -0
- package/dist/{chunk-GB763TSV.js → chunk-TE27J65Q.js} +1 -1
- package/dist/chunk-TE27J65Q.js.map +1 -0
- package/dist/{chunk-46BFUGFL.js → chunk-WIHICNWS.js} +1660 -388
- package/dist/chunk-WIHICNWS.js.map +1 -0
- package/dist/{chunk-UU6EJR52.js → chunk-YU4VRTR4.js} +2 -2
- package/dist/chunk-YU4VRTR4.js.map +1 -0
- package/dist/chunk-ZG2YH25H.js +94 -0
- package/dist/chunk-ZG2YH25H.js.map +1 -0
- package/dist/codex-tool-search.d.ts +5 -4
- package/dist/context-compaction.d.ts +19 -0
- package/dist/gmail-rest-mcp.js +1 -1
- package/dist/index.d.ts +30 -22
- package/dist/index.js +25 -5
- package/dist/lazy-manifest-OEYEHNVY.js +45 -0
- package/dist/lazy-manifest-OEYEHNVY.js.map +1 -0
- package/dist/lazy-manifest.d.ts +6 -0
- package/dist/lazy-tool-transport.d.ts +3 -2
- package/dist/{localSources-PVFCAPN2.js → localSources-TWHTEKGO.js} +3 -2
- package/dist/localSources-TWHTEKGO.js.map +1 -0
- package/dist/metrics.d.ts +6 -0
- package/dist/operational-instructions.d.ts +1 -1
- package/dist/prepared-compaction-request.d.ts +8 -0
- package/dist/provider-history-adapter.d.ts +2 -2
- package/dist/runtime-skills.d.ts +3 -10
- package/dist/sandbox/codemode-client.d.ts +17 -0
- package/dist/sandbox/codemode-token.d.ts +3 -3
- package/dist/sandbox/index.d.ts +2 -1
- package/dist/sandbox/index.js +8 -2
- package/dist/sandbox/materialization-verification-error.d.ts +27 -0
- package/dist/sandbox/provider-command-session.d.ts +44 -2
- package/dist/sandbox/providers/modal-command-control.d.ts +32 -29
- package/dist/sandbox/providers/modal-command-router-wire.d.ts +49 -0
- package/dist/sandbox/providers/modal-command-session.d.ts +2 -1
- package/dist/sandbox/providers/modal-legacy-command-control.d.ts +50 -0
- package/dist/sandbox/providers/modal-materialization-verification.d.ts +7 -0
- package/dist/sandbox/providers/modal.d.ts +0 -8
- package/dist/sandbox/routing/routing-session.d.ts +21 -0
- package/dist/sandbox/turn-tool-cancellation.d.ts +1 -0
- package/dist/skill-library.d.ts +0 -6
- package/dist/skill-library.js +1 -1
- package/dist/workspace-tool-gateway.js +7 -5
- package/package.json +13 -11
- package/src/bundled_artifact_skills/opengeni-documents/SKILL.md +19 -0
- package/src/bundled_artifact_skills/opengeni-documents/references/api.md +22 -0
- package/src/bundled_default_skills/opengeni-client/SKILL.md +349 -0
- package/src/bundled_default_skills/opengeni-client/agents/openai.yaml +4 -0
- package/src/bundled_default_skills/opengeni-client/references/api-workflows.md +256 -0
- package/src/bundled_default_skills/opengeni-client/references/compatibility-and-troubleshooting.md +84 -0
- package/src/bundled_default_skills/opengeni-client/references/customer-skill-template.md +96 -0
- package/src/bundled_default_skills/opengeni-client/references/data-tools-and-credentials.md +99 -0
- package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +81 -0
- package/src/bundled_default_skills/opengeni-client/references/external-users-and-connect.md +457 -0
- package/src/bundled_default_skills/opengeni-client/references/isolation-and-authorization.md +77 -0
- package/src/bundled_default_skills/opengeni-client/references/product-integration-shapes.md +232 -0
- package/src/bundled_default_skills/opengeni-client/references/product-shapes-and-ui.md +116 -0
- package/src/bundled_default_skills/opengeni-client/references/runtime-profile-and-verification.md +157 -0
- package/src/bundled_default_skills/opengeni-help/SKILL.md +101 -0
- package/src/bundled_management_skills/opengeni-skills/SKILL.md +33 -3
- package/src/codex-tool-search.ts +13 -5
- package/src/context-compaction.ts +87 -4
- package/src/gmail-rest-mcp.ts +1 -2
- package/src/index.ts +363 -131
- package/src/lazy-manifest.ts +55 -0
- package/src/lazy-tool-transport.ts +15 -2
- package/src/metrics.ts +6 -0
- package/src/model-request-capture.ts +3 -0
- package/src/operational-instructions.ts +11 -2
- package/src/prepared-compaction-request.ts +51 -0
- package/src/provider-history-adapter.ts +12 -3
- package/src/runtime-skills.ts +3 -17
- package/src/sandbox/codemode-client.ts +204 -0
- package/src/sandbox/codemode-token.ts +7 -2
- package/src/sandbox/index.ts +7 -0
- package/src/sandbox/materialization-verification-error.ts +65 -0
- package/src/sandbox/provider-command-session.ts +70 -2
- package/src/sandbox/providers/modal-command-control.ts +386 -242
- package/src/sandbox/providers/modal-command-router-wire.ts +248 -0
- package/src/sandbox/providers/modal-command-session.ts +177 -4
- package/src/sandbox/providers/modal-legacy-command-control.ts +351 -0
- package/src/sandbox/providers/modal-materialization-verification.ts +122 -0
- package/src/sandbox/providers/modal.ts +1 -9
- package/src/sandbox/routing/routing-session.ts +417 -79
- package/src/sandbox/turn-tool-cancellation.ts +38 -2
- package/src/skill-catalog.ts +1 -0
- package/src/skill-library.ts +0 -6
- package/src/workspace-governance.ts +0 -1
- package/src/workspace-skills.ts +114 -74
- package/dist/chunk-46BFUGFL.js.map +0 -1
- package/dist/chunk-FHGLYLBL.js.map +0 -1
- package/dist/chunk-GB763TSV.js.map +0 -1
- package/dist/chunk-RIJ6DCYS.js.map +0 -1
- package/dist/chunk-UU6EJR52.js.map +0 -1
- /package/dist/{localSources-PVFCAPN2.js.map → chunk-4A4XTKKX.js.map} +0 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
# External users and embedded connection setup
|
|
2
|
+
|
|
3
|
+
Use these APIs only when the installed SDK and deployment expose them. This
|
|
4
|
+
guide describes implemented external identity, service lifecycle, core
|
|
5
|
+
Personal/private session access, and curated OAuth paths—not completion of every
|
|
6
|
+
white-label surface. Optional native linking is explicit delegation, not account
|
|
7
|
+
merging. Full provider coverage remains unfinished. Do not infer guarantees from
|
|
8
|
+
the presence of a contract type.
|
|
9
|
+
|
|
10
|
+
## Optional use of an existing native account
|
|
11
|
+
|
|
12
|
+
Ordinary embedding needs only `asUser`; never require native registration or
|
|
13
|
+
linking for a product user. For an existing OpenGeni user who deliberately wants
|
|
14
|
+
the product to use their native workspace access, begin a link through the
|
|
15
|
+
external client with `beginIdentityLink`. Show the returned challenge only in
|
|
16
|
+
the native consent URL fragment, never its query, logs or analytics. The native
|
|
17
|
+
`/identity-links/:linkId?organization=:organizationId#challenge=:challenge` page
|
|
18
|
+
requires the user's real native login, displays both identities and the requested
|
|
19
|
+
permissions, and permits narrowing before confirmation. The fragment is scrubbed
|
|
20
|
+
before the application mounts. A page reload requires reopening the original
|
|
21
|
+
consent URL. Poll `getIdentityLink` from the product backend for confirmation.
|
|
22
|
+
|
|
23
|
+
After explicit confirmation, choose linked mode on the backend:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
const linked = serviceClient.asLinkedUser(authenticatedUser.id, {
|
|
27
|
+
source: "my-product",
|
|
28
|
+
linkId: confirmedLink.id,
|
|
29
|
+
expectedLinkRevision: confirmedLink.revision,
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Use the same source and opaque ID used at initiation. A confirmed link does not
|
|
34
|
+
change `asUser`, move external sessions or credentials, or merge accounts. New
|
|
35
|
+
linked work belongs to the native user. Requests intersect the key's permissions,
|
|
36
|
+
the live native user's permissions and the approved link ceiling. Never fall back
|
|
37
|
+
to service or external mode when linked authorization fails.
|
|
38
|
+
|
|
39
|
+
Link expiry is optional; null means until revoked. Either confirmed participant
|
|
40
|
+
can revoke using the observed revision. Accepted linked turns, scheduled task
|
|
41
|
+
revisions, child sessions and causal continuations retain the link restriction;
|
|
42
|
+
revocation denies later execution without requiring the original API key to stay
|
|
43
|
+
active. This is an execution-time check, not a promise to undo a remote operation
|
|
44
|
+
already started. Native access to native-owned resources remains intact. Do not
|
|
45
|
+
assume an external user's personal connection transfers to the native owner
|
|
46
|
+
through a link: provision or connect separately while explicitly acting as that
|
|
47
|
+
user. Linked work independently retains the live link restriction.
|
|
48
|
+
`listIdentityLinks(workspaceId, cursor?)`
|
|
49
|
+
provides a participant-only inventory, and native workspace settings expose the
|
|
50
|
+
same list/revoke behavior without retaining the original consent URL.
|
|
51
|
+
|
|
52
|
+
## Separate service administration from user requests
|
|
53
|
+
|
|
54
|
+
Keep one organization-key client on the trusted product backend. After product
|
|
55
|
+
authentication, derive the immutable external identity from the server session:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const actor = serviceClient.asUser(authenticatedUser.id, { source: "my-product" });
|
|
59
|
+
const transport = actor.connectTransport();
|
|
60
|
+
const providers = await transport.catalog(authorizedWorkspaceId);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Here `serviceClient`, `authenticatedUser`, and `authorizedWorkspaceId` are
|
|
64
|
+
host-owned dependencies, not fields accepted from the browser. `asUser` creates
|
|
65
|
+
a separate client and does not mutate the service client. It requires an
|
|
66
|
+
organization key; a workspace key or deployment access key is not a substitute.
|
|
67
|
+
Never retry a denied user request using the unscoped service client.
|
|
68
|
+
|
|
69
|
+
An organization key is trusted to assert and lazily provision product users;
|
|
70
|
+
there is no separate provisioning permission or registration ceremony. The first
|
|
71
|
+
authenticated request may create the identity anchor even if its later workspace
|
|
72
|
+
operation is denied. Workload permissions still restrict that operation. Derive
|
|
73
|
+
IDs from authenticated host records and bound onboarding in the host; never
|
|
74
|
+
forward arbitrary browser-supplied identities. Personal identity anchors are not
|
|
75
|
+
shared product-tenant workspaces or a way to obtain workspace membership.
|
|
76
|
+
|
|
77
|
+
Identity is scoped by organization, source and opaque external ID. Source
|
|
78
|
+
defaults to `default`; use a stable source namespace when multiple identity
|
|
79
|
+
systems share an organization. IDs are case-sensitive, not emails to normalize:
|
|
80
|
+
maximum 1024 UTF-8 bytes for the ID and 200 for source; empty strings, NUL and
|
|
81
|
+
invalid Unicode are rejected. A native-looking ID does not impersonate a native
|
|
82
|
+
user. Workspace mapping identity passed to `ensureWorkspace` is a separate
|
|
83
|
+
concept from this acting-user identity.
|
|
84
|
+
|
|
85
|
+
User mode lazily establishes an external identity but does not grant access to a
|
|
86
|
+
shared workspace. An explicitly authorized service onboarding operation may use:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
await serviceClient.addExternalWorkspaceMember(authorizedWorkspaceId, {
|
|
90
|
+
identity: { externalId: authenticatedUser.id, source: "my-product" },
|
|
91
|
+
permissions: ["workspace:read", "connections:read", "connections:write"],
|
|
92
|
+
operationId: onboardingOperationId,
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Do this only after the host has approved membership, not on every arbitrary
|
|
97
|
+
browser request. The service needs `members:manage` and may not grant authority
|
|
98
|
+
beyond its ceiling. Persist `onboardingOperationId` before the call. Exact keyed
|
|
99
|
+
replays return historical identity without restoring removed membership; different
|
|
100
|
+
permissions conflict instead of overwriting a subsequently reduced grant. Installation also
|
|
101
|
+
needs `capabilities:manage`; do not add it unless installation is a product
|
|
102
|
+
feature the user may perform. User requests intersect actual membership with
|
|
103
|
+
the initiating key's permissions. Service administration remains separate.
|
|
104
|
+
|
|
105
|
+
### Removal and account-wide lifecycle
|
|
106
|
+
|
|
107
|
+
For recoverable onboarding, establish and retain the identity anchor before
|
|
108
|
+
granting membership. Service `lookupExternalIdentity(organizationId, identity)`
|
|
109
|
+
is non-provisioning and returns content-free identity/membership IDs, statuses and
|
|
110
|
+
separate revisions, including suspended/offboarded identities. It requires
|
|
111
|
+
`members:manage` and does not reactivate an identity. A missing result is not proof
|
|
112
|
+
that an earlier unkeyed request cannot still provision one.
|
|
113
|
+
|
|
114
|
+
To withdraw this external member's workspace access while fencing a pending keyed
|
|
115
|
+
grant, call `cancelExternalWorkspaceMemberGrant(organizationId, workspaceId,
|
|
116
|
+
organizationMembershipId, { operationId: cancellationOperationId,
|
|
117
|
+
cancelGrantOperationId: onboardingOperationId })`. Persist both distinct UUIDs;
|
|
118
|
+
retry the exact cancellation body after response loss. This reuses native
|
|
119
|
+
teardown and fences the named grant even if membership is absent. It withdraws
|
|
120
|
+
current workspace membership, not just one session. New grant IDs are explicit
|
|
121
|
+
new onboarding, never retries. Legacy requests without `operationId` remain
|
|
122
|
+
unfenced: drain old writers before claiming late-grant protection.
|
|
123
|
+
|
|
124
|
+
Use the service client's existing `removeWorkspaceMember(workspaceId, subjectId)`
|
|
125
|
+
to remove an external actor from a shared workspace. It requires `members:manage`,
|
|
126
|
+
rechecks the live key, preserves the last-admin guard, and uses the same fenced
|
|
127
|
+
settlement/cancellation path as native removal. It does not disable the actor in
|
|
128
|
+
other workspaces. Ordinary `asUser` reads never restore removed membership.
|
|
129
|
+
|
|
130
|
+
For account-wide changes, call `serviceClient.updateExternalIdentityMembership(
|
|
131
|
+
organizationId, organizationMembershipId, request)`. The membership ID comes from
|
|
132
|
+
the identity returned by onboarding; the initial membership authorization
|
|
133
|
+
revision is 1. The request contains `kind` (`suspend`, `reactivate`, or `offboard`),
|
|
134
|
+
`expectedAuthorizationRevision`, a UUID `operationId`, and optional `reason`.
|
|
135
|
+
Keep the returned membership revision for the next transition. Reuse the exact
|
|
136
|
+
operation ID and body when reconciling an uncertain response, never a different
|
|
137
|
+
transition under the old ID. Replay still requires live service authority.
|
|
138
|
+
|
|
139
|
+
This endpoint requires the organization service key's explicit `account:admin`;
|
|
140
|
+
the external-user lane and native-user targets are rejected. Suspension disables
|
|
141
|
+
new external admission and uses the canonical organization protocol to revoke
|
|
142
|
+
work and grants. Reactivation restores admission only: workspace memberships,
|
|
143
|
+
scheduled work, and resource grants are not restored. Offboarding is terminal
|
|
144
|
+
through this API and follows the existing organization retention policy; it is
|
|
145
|
+
not immediate deletion of history or upstream provider consent. Audit records
|
|
146
|
+
identify the service key separately from native administering memberships.
|
|
147
|
+
|
|
148
|
+
### Personal workspaces and private sessions
|
|
149
|
+
|
|
150
|
+
An admitted external actor can access its exact provisioned Personal workspace;
|
|
151
|
+
`asUser` workspace discovery includes that pointer when the key permits
|
|
152
|
+
`workspace:read`. This is not a service-key fallback, and `ensureWorkspace`
|
|
153
|
+
continues to provision shared product-tenant workspaces only. Personal permissions
|
|
154
|
+
use the same non-administrative owner set as native Personal workspaces,
|
|
155
|
+
intersected with the key ceiling. No Personal member-management wildcard is added.
|
|
156
|
+
|
|
157
|
+
Core session creation, private-read authorization, listing, pinning, visibility
|
|
158
|
+
changes, and same-workspace fork operations use dedicated external owning-user
|
|
159
|
+
proof. The native-cookie flag remains false. Private creation still requires
|
|
160
|
+
platform readiness and, in shared workspaces, the existing organization private
|
|
161
|
+
session setting. Request-time session creation/tenancy commits recheck the live
|
|
162
|
+
key and identity generation; a failed recheck rolls back the mutation. Forking
|
|
163
|
+
private content into workspace visibility retains the existing explicit sharing
|
|
164
|
+
acknowledgment. Private sessions do not make shared-workspace Files or Sites
|
|
165
|
+
private. Full personal-resource, worker, stream, and scheduled-execution parity
|
|
166
|
+
still needs its own integrated verification; do not promise it from these core
|
|
167
|
+
session checks alone.
|
|
168
|
+
|
|
169
|
+
## Host bridge and browser ownership
|
|
170
|
+
|
|
171
|
+
Expose only the Connect operations the product needs through authenticated,
|
|
172
|
+
same-origin backend routes. Every route must authenticate the host session,
|
|
173
|
+
derive the actor and workspace mapping server-side, and apply the host's normal
|
|
174
|
+
CSRF protection to mutations. Never forward an arbitrary upstream URL, actor
|
|
175
|
+
header, organization ID or bearer supplied by the browser. Validate request
|
|
176
|
+
bodies and return credential-free projections; redact errors before display or
|
|
177
|
+
logging. Forward cancellation without assuming it rolls back server effects.
|
|
178
|
+
|
|
179
|
+
The backend transport implements catalog, accounts, pending, begin, get,
|
|
180
|
+
advance, cancel and disconnect. A browser `ConnectTransport` calls those host
|
|
181
|
+
routes; it never contains the organization-key SDK client. Use one
|
|
182
|
+
`ConnectController` per authenticated actor/workspace and dispose it when either
|
|
183
|
+
changes. `@opengeni/react/connect` provides optional unstyled `ConnectChooser`,
|
|
184
|
+
`ConnectSetup`, `ConnectAccounts` and `useConnect`. `ConnectPanel` composes the
|
|
185
|
+
three surfaces; import `@opengeni/react/connect.css` for its opt-in scoped styles.
|
|
186
|
+
The host still owns navigation and controller lifetime. Controller replacement
|
|
187
|
+
clears pending credential forms and prior account/catalog views.
|
|
188
|
+
Providing `returnUrl` to `ConnectAccounts` enables explicit reconnect bound to
|
|
189
|
+
the selected account's provider, ownership and ID; `ConnectPanel` wires this
|
|
190
|
+
automatically. Reconnect does not silently substitute a different account.
|
|
191
|
+
|
|
192
|
+
For a host-owned capability library, `CapabilityCatalogRow` from the same
|
|
193
|
+
subpath supplies the shared icon/name/description row. Provide explicit
|
|
194
|
+
`status` (`available`, `added`, `attention`, `unavailable`, or `loading`) and
|
|
195
|
+
`onOpen`; the plus/check is decorative, not a second action. Normal status
|
|
196
|
+
labels remain accessible and exceptions remain visible. Use one setup entry
|
|
197
|
+
point from the catalog and conversation. Keep provider authentication,
|
|
198
|
+
workspace/account sharing, and explicit Plugin/Skill installation separate;
|
|
199
|
+
matching visual components never grants authority or implies installation.
|
|
200
|
+
When using `ConnectionCatalog`, provide each option's typed `state` to use the
|
|
201
|
+
quiet glyph treatment. Omitting it preserves the existing visible `status`
|
|
202
|
+
string, so older integrations cannot silently lose provider warnings.
|
|
203
|
+
|
|
204
|
+
Wire session timeline `onReconnect` to the host's connection experience. Use
|
|
205
|
+
`findConnectRecoveryAccount` from `@opengeni/connect` with fresh account metadata
|
|
206
|
+
and the event's exact connection ID, then begin setup for that account. A missing
|
|
207
|
+
ID or deleted account requires an explicit user choice, not a provider-name match.
|
|
208
|
+
The product can host the ordinary Connect experience in its own UI. The native
|
|
209
|
+
session and runnable host example use this same exact-account lookup.
|
|
210
|
+
|
|
211
|
+
## Durable OAuth and explicit installation
|
|
212
|
+
|
|
213
|
+
1. Read catalog readiness for the actual actor. The catalog covers generic,
|
|
214
|
+
curated and first-party Connect adapters. Model-account pools retain their
|
|
215
|
+
dedicated SDK APIs and device flow, described below; operator configuration
|
|
216
|
+
is not a user-connect action.
|
|
217
|
+
2. Begin with explicit provider, ownership, a stable idempotency key and the
|
|
218
|
+
exact return URL chosen by the trusted host backend. Persist the attempt ID
|
|
219
|
+
in authenticated host state before navigation. Do not derive the return URL
|
|
220
|
+
from an unchecked browser field.
|
|
221
|
+
3. For popup mode, invoke `authorizeConnectAttempt` directly from a user gesture
|
|
222
|
+
with `createBrowserConnectNavigation(window)`. Blocked popups are errors;
|
|
223
|
+
full redirect is an explicit host choice, not an automatic fallback.
|
|
224
|
+
4. Recover through `get` or authenticated `pending`. The callback preserves the
|
|
225
|
+
stored return URL, including escaping and fragment, without adding status
|
|
226
|
+
parameters. Popup messages and URL parameters never prove completion.
|
|
227
|
+
5. OAuth may commit credentials while the attempt remains
|
|
228
|
+
`connected_but_incomplete`. Advance with `retry` to review an integration
|
|
229
|
+
preview, then submit its preview ID/content hash and explicitly selected
|
|
230
|
+
operation IDs. Never assume OAuth installed all operations.
|
|
231
|
+
6. Changed source requires a new preview and approval. Preserve revision and
|
|
232
|
+
idempotency fields on retries. An uncertain provider effect is not permission
|
|
233
|
+
to start a duplicate mutation with a fresh key.
|
|
234
|
+
|
|
235
|
+
Aborting polling stops observation, not setup. Explicit `cancel` stops setup
|
|
236
|
+
without revoking credentials already committed. `disconnect` currently revokes
|
|
237
|
+
local OpenGeni connection access, not upstream provider consent. Pass the observed
|
|
238
|
+
account `version` as `expectedVersion` to reject a stale selection. The shared
|
|
239
|
+
account component requires that version and explicit confirmation; an unknown
|
|
240
|
+
outcome requires live reload, not automatic replay. Provider-specific account
|
|
241
|
+
management remains unfinished.
|
|
242
|
+
|
|
243
|
+
## Embedded Sites
|
|
244
|
+
|
|
245
|
+
`@opengeni/react/sites` exports `SiteList`, `SiteDetail` and the structural
|
|
246
|
+
`SiteClient` host-proxy interface. The SDK's existing published-artifact methods
|
|
247
|
+
implement it. `asUser` retains the public client class and artifact methods.
|
|
248
|
+
Sites remain workspace-shared artifacts, not private session outputs.
|
|
249
|
+
|
|
250
|
+
Use `SiteList.onOpen` for host navigation. `SiteDetail` reuses the existing
|
|
251
|
+
opaque-origin `PublishedHtmlArtifactFrame`; never introduce a second renderer
|
|
252
|
+
or put backend keys in HTML. Supply only an authenticated, filtered `toolBridge`.
|
|
253
|
+
Use `createSiteToolBridge` from `@opengeni/sdk/site` with the exact artifact ID,
|
|
254
|
+
version ID and that version's `requestedTools`. Provide an authenticated catalog
|
|
255
|
+
transport and `callTool` backed by the host's `callWorkspaceSiteTool` SDK method.
|
|
256
|
+
The native console uses this same bridge. Recreate it when the actor or version
|
|
257
|
+
changes. It strips iframe-supplied authority, pins the Site context, and retries
|
|
258
|
+
only an explicit pre-execution stale-catalog response, never an uncertain effect.
|
|
259
|
+
For the Site's ordinary session SDK, optionally supply `fetchResponse` with your
|
|
260
|
+
authenticated host transport. The shared bridge applies the same bounded
|
|
261
|
+
`siteSessionPath` routing as the native console and forwards only content negotiation
|
|
262
|
+
and event replay headers; host authentication and tenant selection remain outside
|
|
263
|
+
the iframe. The bridge adds its pinned Site ID/version headers (never trusts
|
|
264
|
+
iframe-supplied ones), enabling the API's verified Site-origin attribution on
|
|
265
|
+
new conversations. `originSiteId=current` resolves to that pinned Site for
|
|
266
|
+
conversation filtering. Provenance does not grant access or replace the acting
|
|
267
|
+
user/workspace authority. Keep these headers through your authenticated proxy;
|
|
268
|
+
do not synthesize provenance from caller-supplied session metadata.
|
|
269
|
+
Omit this transport for tools-only Sites. Display uses
|
|
270
|
+
`getWorkspaceArtifactHtml` at the observed version, not a retained-source download.
|
|
271
|
+
It checks Site read authority every 15 seconds while loaded and clears the frame
|
|
272
|
+
on denial, scope replacement or version/status change. This is bounded UI
|
|
273
|
+
revalidation, not instantaneous revocation of downloaded HTML; bridge calls must
|
|
274
|
+
independently enforce current backend authority.
|
|
275
|
+
|
|
276
|
+
`canPublish` controls presentation only. The backend still requires
|
|
277
|
+
`artifacts:publish`; rollback/archive/restore preserve the observed current
|
|
278
|
+
version and require explicit confirmation. Failed mutations clear the loaded
|
|
279
|
+
state and require refresh rather than an unsafe retry. Authoring buttons and
|
|
280
|
+
prompts belong to the host: create an ordinary authorized session and navigate
|
|
281
|
+
to your existing session UI. There is no dedicated SDK authoring helper or
|
|
282
|
+
branded Site component button. Native Site UI reuse
|
|
283
|
+
and complete visual acceptance remain separate integration work.
|
|
284
|
+
|
|
285
|
+
## Credentials and focused acceptance
|
|
286
|
+
|
|
287
|
+
For a named curated API integration account, pass `installationTarget: {
|
|
288
|
+
instanceKey, displayName, expectedInstanceVersion? }` when beginning Connect.
|
|
289
|
+
Reconnect uses the exact current instance version; new accounts omit that version.
|
|
290
|
+
The attempt retains this choice through OAuth, operation preview and installation.
|
|
291
|
+
Without an explicit target, setup creates an independent account rather than
|
|
292
|
+
overwriting a default instance. OAuth success alone still requires operation review.
|
|
293
|
+
|
|
294
|
+
Fiken's `fiken-token` catalog entry is workspace-only. Submit the `apiToken` and
|
|
295
|
+
optional `defaultCompanySlug` fields through the credential action; OpenGeni verifies
|
|
296
|
+
the token and accessible companies before storage. Resume/replay the same attempt
|
|
297
|
+
and operation identity rather than submitting the secret to a new attempt after an
|
|
298
|
+
uncertain response. The separate workspace-only `fiken-oauth` entry uses the
|
|
299
|
+
deployment's registered Fiken OAuth application. It preserves the exact host
|
|
300
|
+
return URL and atomically commits the verified company account and completion
|
|
301
|
+
receipt. Reconnect checks the observed account version; callback replay does not
|
|
302
|
+
repeat the provider exchange. Neither adapter grants personal ownership.
|
|
303
|
+
|
|
304
|
+
Native/local/configured workspace setup and organization/workspace API-key setup
|
|
305
|
+
use the same durable Connect flow where the adapter supports them. Service keys
|
|
306
|
+
cannot create personal connections. Keep keys on the product backend; a callback
|
|
307
|
+
uses its signed initiating principal and current authority, not a new browser login.
|
|
308
|
+
An external Connect attempt also retains its original key/link restriction.
|
|
309
|
+
Changing clients does not replace it: if the initiating key or link was revoked,
|
|
310
|
+
start a new authorized setup rather than expecting a new key to revive the old
|
|
311
|
+
attempt. This short-lived setup rule is separate from accepted agent/scheduled
|
|
312
|
+
work, which does not depend on the original API key remaining active.
|
|
313
|
+
|
|
314
|
+
Use ordinary native connections for both backend provisioning and interactive
|
|
315
|
+
OAuth. An organization-admin backend uses `asUser` to provision a personal
|
|
316
|
+
connection for its canonical user; no separate signup or host binding is needed.
|
|
317
|
+
Persist provisioning operation IDs before requests and reuse them on uncertain
|
|
318
|
+
retries. Select the resulting connection through the native connection authority
|
|
319
|
+
fields; connection visibility is not permission for another participant to use
|
|
320
|
+
its credentials. OAuth refresh remains in the native connection engine.
|
|
321
|
+
|
|
322
|
+
The former host resolver, binding and delegation APIs and selected-host fields
|
|
323
|
+
are removed. Do not build against them or reinterpret their IDs as native
|
|
324
|
+
connection IDs. An optional external credential supplier is future work behind
|
|
325
|
+
the same connection model, not a second setup requirement. See
|
|
326
|
+
`docs/remote-mcp-credentials.md` for the cutover boundary.
|
|
327
|
+
|
|
328
|
+
The request-time workspace tool gateway accepts verified external users and
|
|
329
|
+
organization service keys. Tool catalog/operation permission filtering and
|
|
330
|
+
existing approval semantics still apply. The new lanes recheck current key and
|
|
331
|
+
identity/membership permission ceilings around provider preparation and invocation;
|
|
332
|
+
they do not authorize an agent attempt as a service or inherit a creator's rights.
|
|
333
|
+
The gateway uses the native resolver and rechecks the caller before physical
|
|
334
|
+
requests. It does not call an embedding-product credential callback.
|
|
335
|
+
|
|
336
|
+
Accepted native turn/task selection retains the named actor and exact connection
|
|
337
|
+
authority. A shared conversation does not borrow its creator's credentials for
|
|
338
|
+
another participant. Scheduled occurrences and supported child work consume the
|
|
339
|
+
captured native selection and recheck live authority; token refresh does not
|
|
340
|
+
change the selected account. Existing-session schedules use the target session's
|
|
341
|
+
tools and persisted MCP definitions. Do not add per-endpoint host delegation.
|
|
342
|
+
|
|
343
|
+
Realtime empty-shell creation captures no connection authority. Send its first
|
|
344
|
+
text under the authenticated participant with the native connection selection
|
|
345
|
+
and `clientEventId`; this grants no voice-provider authority.
|
|
346
|
+
|
|
347
|
+
Legacy OAuth starts without verified external continuations fail closed. Curated
|
|
348
|
+
OAuth uses the shared Connect panel. Generic MCP OAuth is also available through
|
|
349
|
+
`actor.startConnectionOAuth(workspaceId, { mcpUrl, returnUrl, ... })`: the trusted
|
|
350
|
+
host backend supplies an exact absolute HTTP(S) return URL, without credentials
|
|
351
|
+
or control/space characters. The signed state encrypts the external continuation;
|
|
352
|
+
callbacks recheck the live key/identity/workspace before exchange and credential
|
|
353
|
+
commit, and consume the nonce before exchange. Both success and failure return
|
|
354
|
+
to the original string without appended parameters; the host must reload
|
|
355
|
+
authenticated connection state rather than treating navigation as proof of
|
|
356
|
+
success. Native `returnPath` behavior is unchanged. The shared panel also offers
|
|
357
|
+
`mcp-oauth`: server URL input, OAuth navigation, pending recovery, account listing
|
|
358
|
+
and reconnect. Its callback commits credentials and the completion receipt in
|
|
359
|
+
one transaction; callback replay never exchanges the code again. Completion is
|
|
360
|
+
connection-only, not an installed integration or a grant to every server tool.
|
|
361
|
+
The `mcp-bearer` adapter accepts a server URL and bearer credential. The
|
|
362
|
+
`mcp-headers` adapter accepts the URL and a JSON object in the secret `headers`
|
|
363
|
+
field for single- or multi-header authentication; transport headers, duplicate
|
|
364
|
+
case-insensitive names and malformed values are rejected before any commit.
|
|
365
|
+
Both persist only
|
|
366
|
+
encrypted material, and uses keyed operation digests. HTTPS without URL userinfo
|
|
367
|
+
or fragment is required. Reconnect keeps the same destination and observed account
|
|
368
|
+
version. Its connection-only completion means the credential was saved, not that
|
|
369
|
+
the server validated it or tools were installed; the normal credential resolver
|
|
370
|
+
enforces the saved MCP destination when it is used. Dedicated workspace model
|
|
371
|
+
provider credentials still use their own guarded flows. Uncertain mutations are
|
|
372
|
+
not automatically retried with a new operation ID.
|
|
373
|
+
Explicit provider denial or missing authorization code before exchange terminates
|
|
374
|
+
the attempt with a replayable failure receipt; start a new attempt to authorize
|
|
375
|
+
again. Unknown exchange or persistence outcomes are not treated as safe retries.
|
|
376
|
+
Provider-specific completion is intentional: a saved credential does not mean
|
|
377
|
+
that repository access, a review webhook, or source synchronization is enabled.
|
|
378
|
+
|
|
379
|
+
`github-personal` preserves personal OAuth account and repository-selection proof.
|
|
380
|
+
`github-app` discovers installations, asks the host user to choose one, then
|
|
381
|
+
requires fresh owner proof before binding repository access. `github-lens` uses
|
|
382
|
+
the same chooser behavior but creates separate Review Bot registrations, webhook
|
|
383
|
+
routing and repository review bindings; it requires managed compute and
|
|
384
|
+
workspace administration plus secret-write permission.
|
|
385
|
+
Neither GitHub App flow is a generic stored user token. Pending organization-owner
|
|
386
|
+
approval is incomplete setup, not a connected account. Discovery currently supports
|
|
387
|
+
at most 99 existing installations plus the new-install option; a larger result
|
|
388
|
+
fails explicitly instead of silently selecting or dropping installations.
|
|
389
|
+
|
|
390
|
+
`slack-bot` is a workspace bot installation, while `slack-personal` is the official
|
|
391
|
+
personal Slack MCP authorization flow. Do not substitute one for the other.
|
|
392
|
+
`x` and `reddit` use the existing social-account domain and OAuth scopes. Workspace
|
|
393
|
+
social setup requires workspace administration; personal setup requires a verified
|
|
394
|
+
owning user. Native and host clients share callback receipts and exact returns.
|
|
395
|
+
Social accounts remain limited by the existing one-personal-account-per-provider
|
|
396
|
+
semantics. Account IDs with `social:`, `github-installation:` and `lens-registration:`
|
|
397
|
+
prefixes are opaque SDK identifiers; use Connect transport disconnect rather than
|
|
398
|
+
passing these to generic credential APIs.
|
|
399
|
+
|
|
400
|
+
Social reconnect requires the observed account ID and version. The callback must
|
|
401
|
+
prove the same upstream account and cannot overwrite a concurrent refresh,
|
|
402
|
+
disconnect or reconnect. Reload accounts after a conflict before asking the user
|
|
403
|
+
to start another attempt.
|
|
404
|
+
|
|
405
|
+
`mcp-install` installs an available, no-credential MCP capability after probing it;
|
|
406
|
+
it does not manufacture a connection. The credential-input action can contain
|
|
407
|
+
bounded `options` for fields: render these as selectors, not free-text account IDs.
|
|
408
|
+
The shared React setup surface already does this for MCP and API-source choices.
|
|
409
|
+
|
|
410
|
+
Model accounts retain their dedicated SDK and pool APIs rather than pretending
|
|
411
|
+
to be ordinary Connect credentials. `pollDeviceAuthorization` from
|
|
412
|
+
`@opengeni/connect` supplies bounded, abortable device polling, and
|
|
413
|
+
`DeviceAuthorization` from `@opengeni/react/connect` supplies optional presentation.
|
|
414
|
+
Keep opaque device state on the server. SuperGrok user pools require ordinary
|
|
415
|
+
workspace membership; a synthetic personal-workspace owner grant alone is not
|
|
416
|
+
enough. Verified external users follow the same restriction as native users.
|
|
417
|
+
|
|
418
|
+
Known Connect callbacks recover the exact saved return URL even after state
|
|
419
|
+
expiry. This is navigation recovery only: expired state cannot exchange or save
|
|
420
|
+
credentials. Poll the attempt for its actual status after returning.
|
|
421
|
+
|
|
422
|
+
`openapi` and `graphql` setup accepts a document/endpoint URL and an optional
|
|
423
|
+
existing connection ID. The server performs pinned source discovery and returns
|
|
424
|
+
an explicit operation preview. Public services do not create fake credentials.
|
|
425
|
+
Installation re-resolves the source and checks its revision/hash, ownership and
|
|
426
|
+
the selected operations. Personal installations require a personal connection.
|
|
427
|
+
The source is immutable once previewed. Each setup gets an independent named
|
|
428
|
+
installation unless the host deliberately supplies an observed instance target.
|
|
429
|
+
|
|
430
|
+
`atlassian`, `google-drive-knowledge` and `google-drive-publish` preserve the
|
|
431
|
+
first-party connectors rather than substituting curated API definitions.
|
|
432
|
+
They require personal ownership; completion means the credential was committed,
|
|
433
|
+
not that all projects, spaces or folders were selected or synchronized.
|
|
434
|
+
Atlassian source selection uses `browseAtlassianSources`, `saveAtlassianSources`
|
|
435
|
+
and `setAtlassianLifecycle`, retaining explicit destination, cadence and read
|
|
436
|
+
policy. Google Drive publishing requires an existing knowledge connection in
|
|
437
|
+
`reconnectAccountId`, additional provider consent and an explicitly picked writable
|
|
438
|
+
folder. Publication writes retain the existing default `ask` policy. Native
|
|
439
|
+
Atlassian and Drive connect buttons consume the same durable setup surface.
|
|
440
|
+
|
|
441
|
+
`examples/embedded-product` is a runnable loopback host reference with explicit
|
|
442
|
+
authentication/CSRF seams, shared Connect/Site UI, and Edit-with-Geni into ordinary
|
|
443
|
+
session hooks/timeline/approval/structured-input, versioned session control, and
|
|
444
|
+
shared durable composer/queue controls, explicit schedule management, and bounded
|
|
445
|
+
workspace-file uploads. Schedule operations retain native permission and approval
|
|
446
|
+
semantics, not a new execution delegation guarantee. Its fixed-user demo auth
|
|
447
|
+
is opt-in and must never be exposed publicly. Native and embedded authoring
|
|
448
|
+
prompts live in their respective products, not the SDK. The example's optional
|
|
449
|
+
trusted `completionHref` keeps completion links in the host product.
|
|
450
|
+
No helper grants tool permissions or changes model billing/approval/scheduling.
|
|
451
|
+
|
|
452
|
+
Test concurrent users without actor-header bleed, cross-workspace denial,
|
|
453
|
+
membership/key permission reduction, exact return URL preservation, pending
|
|
454
|
+
recovery after opener loss, duplicate callbacks, changed-source reapproval and
|
|
455
|
+
explicit operation selection. Keep existing session approvals and scheduling
|
|
456
|
+
semantics. Do not claim provider, browser or scheduled-renewal conformance from
|
|
457
|
+
a transport unit test.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Isolation and authorization
|
|
2
|
+
|
|
3
|
+
## Start from who may share, not from workspace count
|
|
4
|
+
|
|
5
|
+
An OpenGeni organization is the administrative and billing container. An organization workspace is the operational boundary for sessions, events, files, documents, connections, installed capabilities, workspace Knowledge, settings, and agent access.
|
|
6
|
+
|
|
7
|
+
Use the smallest group allowed to share those workspace-scoped capabilities as the workspace mapping unit:
|
|
8
|
+
|
|
9
|
+
| Product requirement | Default mapping | Why |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| A team or tenant may collaborate across all chats | One workspace per team or tenant | Shared sessions and workspace resources match the product rule |
|
|
12
|
+
| Users share workspace resources but their conversations are private | One workspace per tenant; `asUser()` and private session visibility | Canonical ownership protects transcripts without duplicating shared resources |
|
|
13
|
+
| An agent must not reach even its user's other conversations | `agentAccess: "session"` | An additional task-tree boundary, independent of human visibility |
|
|
14
|
+
| Chats may share but data access differs by tenant | At least one workspace per data tenant | Provider authority must never span a tenant that may not share data |
|
|
15
|
+
| Different users access the same data but their chats are private | Shared workspace data and private sessions | Shared upstream data does not make a private transcript shared |
|
|
16
|
+
|
|
17
|
+
Other mappings are valid when the product explicitly accepts their sharing semantics. Document that decision; do not use workspace count alone as an optimization goal.
|
|
18
|
+
|
|
19
|
+
A workspace is control-plane state, not a dedicated cluster or permanently running sandbox. Creating one adds database/configuration state and may require repeated capability or Connection provisioning, but compute is established for sessions when needed. Hundreds of workspaces are not inherently exceptional. Per-chat workspaces have more lifecycle and connector-management overhead, so automate reconciliation and deletion instead of weakening a hard privacy requirement.
|
|
20
|
+
|
|
21
|
+
## Current session authority facts
|
|
22
|
+
|
|
23
|
+
- A top-level session created by an organization API key defaults to workspace visibility.
|
|
24
|
+
- Private or Only-me sessions require verified owning-user authority and organization activation. Native managed sessions and the server-side `asUser()` path establish that authority; a raw `endUser` payload does not.
|
|
25
|
+
- An agent must pass ordinary permissions and private-session ownership checks. The caller's `agentAccess` narrows outbound reach: `session` stays in its root tree; `user` requires matching non-null canonical scope users across trees; `workspace` adds no further restriction. The target's `agentAccess` never restricts inbound access. None of these modes overrides private visibility.
|
|
26
|
+
- Knowledge learning controls agent authoring. Turning it off leaves authorized retrieval available and does not remove session history, change session visibility, or neutralize cross-session tools.
|
|
27
|
+
- Hiding session-list and session-get alone is incomplete. Events, waiting, messaging, control, discovery, workspace Knowledge, documents, notes, or other workspace-wide tools may still cross the intended boundary.
|
|
28
|
+
|
|
29
|
+
One workspace per end user or One workspace per chat remains possible when the
|
|
30
|
+
resources and integration configuration themselves must be isolated, but is not
|
|
31
|
+
required merely to make a conversation private. Use the canonical private
|
|
32
|
+
session boundary for transcripts; choose separate workspaces for workspace
|
|
33
|
+
resources. Remove unnecessary tools as defense in depth, never as a substitute
|
|
34
|
+
for either boundary. Personal Knowledge follows the verified active-turn user; task
|
|
35
|
+
notes cover task-local coordination. Session-scoped Memory is retired without
|
|
36
|
+
promoting historical rows into workspace visibility.
|
|
37
|
+
|
|
38
|
+
## Explicit headless tool policy
|
|
39
|
+
|
|
40
|
+
For a customer-facing headless session, never rely accidentally on omission:
|
|
41
|
+
|
|
42
|
+
- Omitting tools uses the workspace's configured MCP defaults; an explicit empty tools list suppresses them.
|
|
43
|
+
- Omitting firstPartyMcpTools selects the deployment's non-connector default catalog; an explicit empty list exposes none.
|
|
44
|
+
- Build an allowlist from the product's actual use case and the live SDK type or client configuration.
|
|
45
|
+
- Exclude cross-session tools unless collaboration is an explicit feature. Current examples include sessions_list, session_get, session_events, session_wait, session_send_message, session_pause, session_resume, session_steer, session_human_input_respond, set_other_session_title, and workspace-scoped discovery. Recheck the live catalog rather than treating this list as permanent.
|
|
46
|
+
- Also examine Knowledge, notes, files, artifacts, browsers, computers, scheduling, and capability-management tools. A tool is safe only when both its scope and its necessity fit the product.
|
|
47
|
+
- A tool allowlist narrows what the model can invoke; it does not repair an incorrectly shared workspace, an over-broad provider token, or a vulnerable customer API.
|
|
48
|
+
|
|
49
|
+
## Backend mapping pattern
|
|
50
|
+
|
|
51
|
+
The product backend should:
|
|
52
|
+
|
|
53
|
+
1. Authenticate the product request using the product's existing identity system.
|
|
54
|
+
2. Derive the canonical sharing boundary from trusted server-side identity, such as tenant ID, user ID, or conversation ID.
|
|
55
|
+
3. Resolve or lazily ensure the corresponding organization workspace with a stable externalSource plus externalId pair.
|
|
56
|
+
4. Persist the returned opaque workspace ID with the product boundary record.
|
|
57
|
+
5. Resolve the product's own session-to-OpenGeni-session mapping before every read, stream, message, control, or upload operation.
|
|
58
|
+
6. Reject caller-supplied OpenGeni workspace or session IDs that do not match those mappings.
|
|
59
|
+
|
|
60
|
+
The externalId passed to `ensureWorkspace` identifies the product boundary; it does not create an OpenGeni human. A service-mode integration need not create one OpenGeni account or workspace membership per end user. External user mode is distinct: `asUser` lazily resolves an organization-scoped external identity, and shared access requires explicit membership intersected with the initiating key's permissions. See [External users and Connect](external-users-and-connect.md) for onboarding and current limitations. Provision workspaces lazily on first use, from a product lifecycle event, or through a controlled backfill according to operational needs. The ensure call is idempotent and should use the same identity on retries.
|
|
61
|
+
|
|
62
|
+
An organization API key is intentionally broad across organization workspaces. Keep it in the backend secret manager. Where a component needs only one workspace, consider a narrower workspace key. In either case the customer's backend remains responsible for mapping its authenticated principal to the correct OpenGeni boundary.
|
|
63
|
+
|
|
64
|
+
## Isolation verification
|
|
65
|
+
|
|
66
|
+
Include negative tests, not only a successful chat:
|
|
67
|
+
|
|
68
|
+
- User A cannot open, stream, message, or attach a file to user B's mapped session through product routes.
|
|
69
|
+
- A manipulated browser request carrying another workspace or session ID is rejected before the OpenGeni call.
|
|
70
|
+
- A prompt that names or guesses another session cannot make the agent retrieve it with the selected tools.
|
|
71
|
+
- Workspaces created concurrently for the same boundary converge on one mapping; distinct boundary IDs never converge.
|
|
72
|
+
- Provider credentials and API tools cannot request another tenant merely by changing a request argument.
|
|
73
|
+
- Deleting or disabling a product user applies the customer's chosen session/workspace retention and access policy.
|
|
74
|
+
|
|
75
|
+
For same-workspace private sessions, verify ownership through HTTP, tools,
|
|
76
|
+
lists and streams; also verify optional agent reach independently. Test the
|
|
77
|
+
effective tool policy as defense in depth, not as proof of ownership enforcement.
|