@botiverse/porthole 0.1.1 → 0.1.3

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 (96) hide show
  1. package/dist/annotate/types.d.ts +120 -0
  2. package/dist/annotate/types.js +42 -0
  3. package/dist/annotate/validate.d.ts +11 -0
  4. package/dist/annotate/validate.js +156 -0
  5. package/dist/bridge/bridge.d.ts +4 -0
  6. package/dist/bridge/bridge.js +12 -1
  7. package/dist/compile/policy.d.ts +5 -3
  8. package/dist/compile/policy.js +8 -4
  9. package/dist/config/capabilities.d.ts +37 -4
  10. package/dist/config/capabilities.js +20 -0
  11. package/dist/config/schema.d.ts +8 -0
  12. package/dist/config/schema.js +5 -0
  13. package/dist/config/validate.js +15 -1
  14. package/dist/conformance/clipboard.d.ts +2 -0
  15. package/dist/conformance/clipboard.js +167 -0
  16. package/dist/conformance/kit.d.ts +1 -1
  17. package/dist/conformance/probes.js +2 -0
  18. package/dist/guide/guide.js +8 -4
  19. package/dist/host/clipboard.d.ts +11 -0
  20. package/dist/host/clipboard.js +43 -0
  21. package/dist/host/create-host.js +141 -0
  22. package/dist/host/outcome.d.ts +1 -0
  23. package/dist/host/outcome.js +19 -6
  24. package/dist/host/types.d.ts +34 -5
  25. package/dist/index.d.ts +8 -4
  26. package/dist/index.js +8 -3
  27. package/dist/mcp/adapter.js +10 -1
  28. package/dist/presets/presets.d.ts +3 -1
  29. package/dist/presets/presets.js +1 -0
  30. package/dist/protocol/mcp-apps.d.ts +5 -0
  31. package/dist/protocol/mcp-apps.js +5 -0
  32. package/dist/protocol/shell-adapter.js +6 -2
  33. package/dist/react/dialog.js +2 -0
  34. package/dist/react/frame.d.ts +18 -0
  35. package/dist/react/frame.js +82 -2
  36. package/dist/react/index.d.ts +2 -1
  37. package/dist/react/index.js +2 -1
  38. package/dist/react/toast.d.ts +33 -0
  39. package/dist/react/toast.js +42 -0
  40. package/dist/server/crypto.d.ts +19 -0
  41. package/dist/server/crypto.js +144 -0
  42. package/dist/server/index.d.ts +12 -4
  43. package/dist/server/index.js +11 -3
  44. package/dist/server/keys.js +12 -9
  45. package/dist/server/naming.d.ts +17 -0
  46. package/dist/server/naming.js +34 -0
  47. package/dist/server/pages.d.ts +1 -1
  48. package/dist/server/pages.js +13 -5
  49. package/dist/server/server.js +162 -18
  50. package/dist/server/tickets.d.ts +24 -0
  51. package/dist/server/tickets.js +46 -0
  52. package/dist/server/types.d.ts +76 -5
  53. package/dist/shell/annotate.d.ts +20 -0
  54. package/dist/shell/annotate.js +669 -0
  55. package/dist/shell/document.js +4 -1
  56. package/dist/shell/plan.d.ts +2 -0
  57. package/dist/shell/plan.js +2 -1
  58. package/dist/shell/runtime.d.ts +4 -1
  59. package/dist/shell/runtime.js +38 -2
  60. package/package.json +2 -1
  61. package/src/annotate/types.ts +126 -0
  62. package/src/annotate/validate.ts +186 -0
  63. package/src/bridge/bridge.ts +13 -0
  64. package/src/compile/policy.ts +8 -4
  65. package/src/config/capabilities.ts +33 -3
  66. package/src/config/schema.ts +10 -0
  67. package/src/config/validate.ts +16 -1
  68. package/src/conformance/clipboard.ts +184 -0
  69. package/src/conformance/kit.ts +1 -1
  70. package/src/conformance/probes.ts +2 -0
  71. package/src/guide/guide.ts +19 -4
  72. package/src/host/clipboard.ts +41 -0
  73. package/src/host/create-host.ts +155 -0
  74. package/src/host/outcome.ts +25 -7
  75. package/src/host/types.ts +39 -5
  76. package/src/index.ts +31 -1
  77. package/src/mcp/adapter.ts +10 -1
  78. package/src/presets/presets.ts +4 -0
  79. package/src/protocol/mcp-apps.ts +6 -0
  80. package/src/protocol/shell-adapter.ts +11 -2
  81. package/src/react/dialog.tsx +2 -0
  82. package/src/react/frame.tsx +117 -1
  83. package/src/react/index.ts +9 -1
  84. package/src/react/toast.tsx +96 -0
  85. package/src/server/crypto.ts +166 -0
  86. package/src/server/index.ts +20 -3
  87. package/src/server/keys.ts +21 -13
  88. package/src/server/naming.ts +42 -0
  89. package/src/server/pages.ts +13 -4
  90. package/src/server/server.ts +190 -20
  91. package/src/server/tickets.ts +65 -0
  92. package/src/server/types.ts +84 -7
  93. package/src/shell/annotate.ts +669 -0
  94. package/src/shell/document.ts +6 -1
  95. package/src/shell/plan.ts +4 -1
  96. package/src/shell/runtime.ts +38 -2
@@ -10,11 +10,41 @@ export interface ContentDomain {
10
10
  /** `http` only for `localhost`. */
11
11
  readonly scheme: "https" | "http";
12
12
  readonly port?: number;
13
+ /**
14
+ * The label under `domain` a storage scope is served on (P047). Default: 24 base32 characters
15
+ * keyed from the scope with the server's secret (stable, not guessable). A host's own (flat
16
+ * names like `a-<id>`) must return one lowercase DNS label, the same for the same scope, a
17
+ * different one for a different scope, and never a `reserved` one.
18
+ */
19
+ readonly name?: (scope: string) => string;
20
+ /**
21
+ * Labels this server never serves or names (another server's namespace under the same domain,
22
+ * `f` for `<instance>.f.<domain>`, or `www`). Requests for them get null (the host's routes).
23
+ */
24
+ readonly reserved?: readonly string[];
13
25
  }
14
- /** Who may open an instance, decided by the host before it calls `issue`. */
15
- export interface Grant {
26
+ /**
27
+ * Who may open an instance, decided by the host before it calls `issue`: a viewer the host
28
+ * knows, or (a public link) nobody in particular. Porthole never interprets either: identity and
29
+ * authorization policy are the host's (P050).
30
+ */
31
+ export type Grant = ({
16
32
  /** The host's id for the viewer: recorded with the ticket, never shown to content. */
17
33
  readonly viewer: string;
34
+ readonly anonymous?: never;
35
+ } | {
36
+ /**
37
+ * A public link: no viewer (P046). Only for documents (a shell, an artifact version, the
38
+ * sandbox proxy), never for a url-mode app.
39
+ */
40
+ readonly anonymous: true;
41
+ readonly viewer?: never;
42
+ }) & {
43
+ /**
44
+ * The host's own opaque claim, carried in the ticket and the session cookie and handed back to
45
+ * `authorize` on every request (a session id, a share id). At most 512 characters.
46
+ */
47
+ readonly subject?: string;
18
48
  /** How long the ticket is good for, seconds (default 60). */
19
49
  readonly ttlSeconds?: number;
20
50
  /**
@@ -22,10 +52,13 @@ export interface Grant {
22
52
  * url-mode app's every request, rides on.
23
53
  */
24
54
  readonly sessionSeconds?: number;
25
- }
55
+ };
26
56
  export interface TicketRecord {
27
57
  readonly instance: InstanceRef;
58
+ /** The grant's viewer; "" for an anonymous grant. */
28
59
  readonly viewer: string;
60
+ readonly anonymous?: boolean;
61
+ readonly subject?: string;
29
62
  /** Epoch milliseconds. */
30
63
  readonly expiresAt: number;
31
64
  /** The grant's `sessionSeconds`, if it set one. */
@@ -46,7 +79,11 @@ export interface ArtifactStore {
46
79
  /** What a request's cookie lets in: one instance, for one viewer, on one origin, until a time. */
47
80
  export interface Access {
48
81
  readonly instance: InstanceRef;
82
+ /** The grant's viewer; "" for an anonymous one. */
49
83
  readonly viewer: string;
84
+ readonly anonymous?: boolean;
85
+ /** The grant's opaque subject, if it had one. */
86
+ readonly subject?: string;
50
87
  /** The content origin the access is for. */
51
88
  readonly origin: string;
52
89
  /** When the cookie stops being good, epoch milliseconds. */
@@ -58,6 +95,37 @@ export interface Access {
58
95
  * Porthole's cookie; the answer gets `frame-ancestors` added, and loses any cookie named as ours.
59
96
  */
60
97
  export type Upstream = (request: Request, access: Access) => Response | Promise<Response>;
98
+ /** What `authorize` is asked about: a request the cookie (or ticket) let in. */
99
+ export interface AuthorizeRequest {
100
+ readonly scope: string;
101
+ readonly instance: InstanceRef;
102
+ readonly viewer: string;
103
+ readonly anonymous: boolean;
104
+ readonly subject?: string;
105
+ /** The request itself (its path, method; never its Porthole cookie's value). */
106
+ readonly request: Request;
107
+ }
108
+ /** The host's answer: let it in, or not (with a short reason code for the host's own UI). */
109
+ export type AuthorizeAnswer = {
110
+ readonly allow: true;
111
+ } | {
112
+ readonly allow: false;
113
+ /** A short code (`revoked`, `left-workspace`): lowercase letters, digits and dashes. */
114
+ readonly code?: string;
115
+ };
116
+ /**
117
+ * The host's check on every request its cookie lets in (P050): revocation, membership,
118
+ * liveness. Porthole calls it after the cookie (or ticket) verifies and before anything of the
119
+ * content is served; a deny is a 403 page that tells the host why (`blocked: denied`).
120
+ */
121
+ export interface Authorizer {
122
+ check(request: AuthorizeRequest): AuthorizeAnswer | Promise<AuthorizeAnswer>;
123
+ /**
124
+ * How long an answer may be reused for the same session and scope, seconds. Default 0: asked
125
+ * on every request. A host opts into a short time for apps with many requests.
126
+ */
127
+ readonly ttlSeconds?: number;
128
+ }
61
129
  export interface ServerOptions {
62
130
  readonly content: ContentDomain;
63
131
  /** At least 32 random bytes: keys the labels and signs tickets and cookies. */
@@ -73,6 +141,8 @@ export interface ServerOptions {
73
141
  readonly tickets?: TicketStore;
74
142
  /** Url mode: where an external instance's requests go once let in. Absent: nothing serves them. */
75
143
  readonly upstream?: Upstream;
144
+ /** The host's per-request check (P050). Absent: a good cookie is enough until it ends. */
145
+ readonly authorize?: Authorizer;
76
146
  }
77
147
  export interface PortholeServer {
78
148
  /**
@@ -88,8 +158,9 @@ export interface PortholeServer {
88
158
  */
89
159
  issue(instance: InstanceRef, grant: Grant): Promise<FrameLocation>;
90
160
  /**
91
- * The access a request's cookie carries for a url-mode app on the request's origin, or null:
92
- * for a host's own WebSocket upgrade path, which a fetch-style handler can't take.
161
+ * The access a request's cookie carries for a url-mode app on the request's origin, or null
162
+ * (no good cookie, or the host's check denies it): for a host's own WebSocket upgrade path,
163
+ * which a fetch-style handler can't take.
93
164
  */
94
165
  access(request: Request): Promise<Access | null>;
95
166
  /** The frame source every content origin matches (`https://*.example-usercontent.com`). */
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The shell's annotation runtime (P053), spliced into the shell's runtime (`__ANNOTATE__`) when
3
+ * the config declares `annotate`, so it runs before any content does, with the DOM's own
4
+ * functions as they were. Plain ES2020 like the rest of the shell; no template literals (it sits
5
+ * in one).
6
+ *
7
+ * The host drives it (`porthole/annotate.start|stop|show|focus|clear`) and it reports
8
+ * (`porthole/annotate.selected|unselected|cancelled|anchored`):
9
+ * - picking an element: the element under the pointer (or finger) is outlined with its name; a
10
+ * click or tap picks it, and the content's own handlers never see that click; Escape cancels;
11
+ * - selecting text: each selection that settles is reported, with where it is, and its clearing;
12
+ * - marks: each anchor is found in the content as it is now (its CSS selector, its text where it
13
+ * was, its text anywhere, its words with any spacing) and drawn over it, in a layer of the
14
+ * shell's own (a closed shadow root), again whenever the content changes; what can't be found
15
+ * is reported `orphaned`.
16
+ *
17
+ * It shares the realm with the content, which can interfere with all of it: the host takes its
18
+ * reports as UI hints only.
19
+ */
20
+ export declare const ANNOTATE_RUNTIME: string;