@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
@@ -11,12 +11,45 @@ export interface ContentDomain {
11
11
  /** `http` only for `localhost`. */
12
12
  readonly scheme: "https" | "http";
13
13
  readonly port?: number;
14
+ /**
15
+ * The label under `domain` a storage scope is served on (P047). Default: 24 base32 characters
16
+ * keyed from the scope with the server's secret (stable, not guessable). A host's own (flat
17
+ * names like `a-<id>`) must return one lowercase DNS label, the same for the same scope, a
18
+ * different one for a different scope, and never a `reserved` one.
19
+ */
20
+ readonly name?: (scope: string) => string;
21
+ /**
22
+ * Labels this server never serves or names (another server's namespace under the same domain,
23
+ * `f` for `<instance>.f.<domain>`, or `www`). Requests for them get null (the host's routes).
24
+ */
25
+ readonly reserved?: readonly string[];
14
26
  }
15
27
 
16
- /** Who may open an instance, decided by the host before it calls `issue`. */
17
- export interface Grant {
18
- /** The host's id for the viewer: recorded with the ticket, never shown to content. */
19
- readonly viewer: string;
28
+ /**
29
+ * Who may open an instance, decided by the host before it calls `issue`: a viewer the host
30
+ * knows, or (a public link) nobody in particular. Porthole never interprets either: identity and
31
+ * authorization policy are the host's (P050).
32
+ */
33
+ export type Grant = (
34
+ | {
35
+ /** The host's id for the viewer: recorded with the ticket, never shown to content. */
36
+ readonly viewer: string;
37
+ readonly anonymous?: never;
38
+ }
39
+ | {
40
+ /**
41
+ * A public link: no viewer (P046). Only for documents (a shell, an artifact version, the
42
+ * sandbox proxy), never for a url-mode app.
43
+ */
44
+ readonly anonymous: true;
45
+ readonly viewer?: never;
46
+ }
47
+ ) & {
48
+ /**
49
+ * The host's own opaque claim, carried in the ticket and the session cookie and handed back to
50
+ * `authorize` on every request (a session id, a share id). At most 512 characters.
51
+ */
52
+ readonly subject?: string;
20
53
  /** How long the ticket is good for, seconds (default 60). */
21
54
  readonly ttlSeconds?: number;
22
55
  /**
@@ -24,11 +57,14 @@ export interface Grant {
24
57
  * url-mode app's every request, rides on.
25
58
  */
26
59
  readonly sessionSeconds?: number;
27
- }
60
+ };
28
61
 
29
62
  export interface TicketRecord {
30
63
  readonly instance: InstanceRef;
64
+ /** The grant's viewer; "" for an anonymous grant. */
31
65
  readonly viewer: string;
66
+ readonly anonymous?: boolean;
67
+ readonly subject?: string;
32
68
  /** Epoch milliseconds. */
33
69
  readonly expiresAt: number;
34
70
  /** The grant's `sessionSeconds`, if it set one. */
@@ -50,7 +86,11 @@ export interface ArtifactStore {
50
86
  /** What a request's cookie lets in: one instance, for one viewer, on one origin, until a time. */
51
87
  export interface Access {
52
88
  readonly instance: InstanceRef;
89
+ /** The grant's viewer; "" for an anonymous one. */
53
90
  readonly viewer: string;
91
+ readonly anonymous?: boolean;
92
+ /** The grant's opaque subject, if it had one. */
93
+ readonly subject?: string;
54
94
  /** The content origin the access is for. */
55
95
  readonly origin: string;
56
96
  /** When the cookie stops being good, epoch milliseconds. */
@@ -64,6 +104,40 @@ export interface Access {
64
104
  */
65
105
  export type Upstream = (request: Request, access: Access) => Response | Promise<Response>;
66
106
 
107
+ /** What `authorize` is asked about: a request the cookie (or ticket) let in. */
108
+ export interface AuthorizeRequest {
109
+ readonly scope: string;
110
+ readonly instance: InstanceRef;
111
+ readonly viewer: string;
112
+ readonly anonymous: boolean;
113
+ readonly subject?: string;
114
+ /** The request itself (its path, method; never its Porthole cookie's value). */
115
+ readonly request: Request;
116
+ }
117
+
118
+ /** The host's answer: let it in, or not (with a short reason code for the host's own UI). */
119
+ export type AuthorizeAnswer =
120
+ | { readonly allow: true }
121
+ | {
122
+ readonly allow: false;
123
+ /** A short code (`revoked`, `left-workspace`): lowercase letters, digits and dashes. */
124
+ readonly code?: string;
125
+ };
126
+
127
+ /**
128
+ * The host's check on every request its cookie lets in (P050): revocation, membership,
129
+ * liveness. Porthole calls it after the cookie (or ticket) verifies and before anything of the
130
+ * content is served; a deny is a 403 page that tells the host why (`blocked: denied`).
131
+ */
132
+ export interface Authorizer {
133
+ check(request: AuthorizeRequest): AuthorizeAnswer | Promise<AuthorizeAnswer>;
134
+ /**
135
+ * How long an answer may be reused for the same session and scope, seconds. Default 0: asked
136
+ * on every request. A host opts into a short time for apps with many requests.
137
+ */
138
+ readonly ttlSeconds?: number;
139
+ }
140
+
67
141
  export interface ServerOptions {
68
142
  readonly content: ContentDomain;
69
143
  /** At least 32 random bytes: keys the labels and signs tickets and cookies. */
@@ -79,6 +153,8 @@ export interface ServerOptions {
79
153
  readonly tickets?: TicketStore;
80
154
  /** Url mode: where an external instance's requests go once let in. Absent: nothing serves them. */
81
155
  readonly upstream?: Upstream;
156
+ /** The host's per-request check (P050). Absent: a good cookie is enough until it ends. */
157
+ readonly authorize?: Authorizer;
82
158
  }
83
159
 
84
160
  export interface PortholeServer {
@@ -95,8 +171,9 @@ export interface PortholeServer {
95
171
  */
96
172
  issue(instance: InstanceRef, grant: Grant): Promise<FrameLocation>;
97
173
  /**
98
- * The access a request's cookie carries for a url-mode app on the request's origin, or null:
99
- * for a host's own WebSocket upgrade path, which a fetch-style handler can't take.
174
+ * The access a request's cookie carries for a url-mode app on the request's origin, or null
175
+ * (no good cookie, or the host's check denies it): for a host's own WebSocket upgrade path,
176
+ * which a fetch-style handler can't take.
100
177
  */
101
178
  access(request: Request): Promise<Access | null>;
102
179
  /** The frame source every content origin matches (`https://*.example-usercontent.com`). */