@collective-intelligence/external-apps-server-sdk 0.1.17 → 0.1.19

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/README.md CHANGED
@@ -651,53 +651,31 @@ await ci.origins.setRuntime({
651
651
  - It needs the `origins:write` scope. Only service credentials may call it: a
652
652
  delegated user token or an anonymous visitor gets `operation_not_allowed`.
653
653
 
654
- ## Member company links
654
+ ## Records a user acts for
655
655
 
656
- An application links a member of its Organization to the Knowledge company
657
- entities the member acts for. A member can have several companies and a company
658
- several members.
656
+ A schema declares its accounts field to name the users that act for each of its
657
+ records (see the [Knowledge User fields](../../../docs/reference/knowledge-user-fields.md)
658
+ reference). CI stores no other link between a user and a record, and offers no
659
+ operation that lists or changes one: write the accounts field as an
660
+ administrator, with the workflow account step or with the Default Server Role
661
+ credential. A policy reads the field as `resource` path `["data", "accounts"]`
662
+ and the caller as `subject` path `["user", "id"]`.
659
663
 
660
- ```ts
661
- const linked = await ci.users.linkCompanies({
662
- entityIds: [companyEntityId],
663
- organizationId,
664
- userId
665
- })
666
- // linked.value.result: { entityIds } — all of the user's links
667
-
668
- const links = await ci.users.listCompanyLinks({ organizationId, userId })
669
- ```
670
-
671
- - Only confidential service credentials may call these operations: a delegated
672
- user token or an anonymous visitor gets `operation_not_allowed`, and the
673
- browser client and user proxy do not offer them.
674
- - The Organization is the caller's. A user without membership in it, or an
675
- entity that is missing, deleted, or in another Organization, returns
676
- `not_found`; a refused call links nothing.
677
- - Linking keeps existing links, so a retried call converges. Results list the
678
- user's linked entities in entity id order.
679
- - `knowledge:write` gates `linkCompanies`; `knowledge:read` gates
680
- `listCompanyLinks`.
681
- - CI accepts any entity of the Organization and does not check its schema; the
682
- calling application decides which entities count as companies.
683
- - Entity deduplication moves links to the surviving entity; physically deleting
684
- an entity removes its links.
685
664
  - A delegated user's `/application/v1/resources` and `knowledge_*` calls, and
686
- the Agents, Skills and workflows the user runs, carry the user's links to
687
- Knowledge policy as `subject.linkedCompanyIds`, and a policy reads the
688
- entity id as `resource` path `["id"]`. CI also sets `subject.access`:
689
- `"read"` for gets, lists, searches, facets, autocomplete, traversal and
690
- retrieval, `"write"` for creates, updates, deletes and relation writes. The
691
- operation sets it; a caller cannot. A policy that does not test `access`
692
- applies to reads and writes alike.
665
+ the Agents, Skills and workflows the user runs, decide under the user's
666
+ Knowledge policy subject. CI sets `subject.access`: `"read"` for gets, lists,
667
+ searches, facets, autocomplete, traversal and retrieval, `"write"` for
668
+ creates, updates, deletes and relation writes. The operation sets it; a
669
+ caller cannot. A policy that does not test `access` applies to reads and
670
+ writes alike.
693
671
  - To let `member`-role users write only their own companies but read every
694
672
  company (for example through member-run Agents), declare a `deny` `filter`
695
673
  policy on the company schema: subject match `user.role` equals `member` and
696
- `access` equals `write`, rule "entity id not in `linkedCompanyIds`". Updates
697
- and deletes of any other company, and creates, then fail with `forbidden`;
698
- gets, lists and searches still return it. Without the `access` clause the
699
- same policy also hides other companies from reads. Other roles and service
700
- credentials are unaffected.
674
+ `access` equals `write`, rule "`subject.user.id` not in
675
+ `resource.data.accounts`". Updates and deletes of any other company, and
676
+ creates, then fail with `forbidden`; gets, lists and searches still return it.
677
+ Without the `access` clause the same policy also hides other companies from
678
+ reads. Other roles and service credentials are unaffected.
701
679
  - The policy binds an execution only while it acts as the member. An Agent or
702
680
  Skill tool bound to a fixed user, or a workflow that runs as another user or
703
681
  a service principal, decides as that principal, not as the member who
@@ -1562,6 +1540,37 @@ and is not forwarded. A local `defineEntityResource` binding answers
1562
1540
  `capability_not_supported`, and a `defineCrudResource` handler answers 404 for
1563
1541
  this path. The client SDK README documents the write form.
1564
1542
 
1543
+ ### Realtime ticket route
1544
+
1545
+ A browser opens the CI realtime stream with a single-use ticket, never with the
1546
+ user's token. Add `realtime` to the BFF; it mounts
1547
+ `POST {basePath}/realtime/ticket` (`basePath` defaults to `/api`) ahead of the
1548
+ dedicated Capability prefix:
1549
+
1550
+ ```ts
1551
+ createExternalApplicationBffNextHandlers({
1552
+ auth,
1553
+ publicOrigin: env.APP_ORIGIN,
1554
+ realtime: {
1555
+ organizationId: env.CI_ORGANIZATION_ID,
1556
+ tenantUrl: env.CI_TENANT_URL,
1557
+ // Optional: the origin the browser opens the stream on.
1558
+ host: "https://realtime.example.com"
1559
+ }
1560
+ })
1561
+ ```
1562
+
1563
+ The route accepts `{ topics }` as JSON from the application's own origin
1564
+ (cross-site requests answer 403), reads the signed-in user's server-held
1565
+ delegated token, and calls CI `POST /application/v1/realtime/tickets` with it.
1566
+ It answers `{ ticket, expiresAt, streamUrl }`; `streamUrl` is
1567
+ `{host}/application/v1/realtime/events?ticket=…`, and `host` defaults to
1568
+ `tenantUrl`. Without a session it answers 401 before calling CI. CI refusals
1569
+ keep their status, body, and `Retry-After`: 429 `too_many_connections` at the
1570
+ per-user connection cap, 503 `unavailable`. Use
1571
+ `createRealtimeTicketHandler` from `/runtime/web` or `/runtime/next` to mount
1572
+ the route yourself. The client SDK README documents the browser client.
1573
+
1565
1574
  ## Optional local user authentication
1566
1575
 
1567
1576
  Import `createBetterAuth` only from