@lotics/app-sdk 0.55.0 → 0.55.1
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/src/rpc.d.ts +10 -0
- package/dist/src/rpc.js +13 -3
- package/docs/runtime.md +6 -2
- package/package.json +1 -1
package/dist/src/rpc.d.ts
CHANGED
|
@@ -159,6 +159,16 @@ export interface AgentRunContinuePayload {
|
|
|
159
159
|
* `rpcAgentRun` streams the first.
|
|
160
160
|
*/
|
|
161
161
|
export declare function rpcAgentRunContinue(payload: AgentRunContinuePayload, onText: (chunk: string) => void): AgentRunHandle;
|
|
162
|
+
/**
|
|
163
|
+
* The password-session header. It is deliberately NOT `Authorization`: this
|
|
164
|
+
* token authenticates nobody — it proves the visitor knows the app's shared
|
|
165
|
+
* link password — and the credential header already carries API keys and OAuth
|
|
166
|
+
* bearers. Sharing it meant the server's auth middleware rejected the request
|
|
167
|
+
* as an unknown bearer before the password gate ever ran, which took every
|
|
168
|
+
* password-gated public app offline. Wire constant, mirrored server-side by
|
|
169
|
+
* `APP_PUBLIC_SESSION_HEADER`; both sides are pinned by tests.
|
|
170
|
+
*/
|
|
171
|
+
export declare const APP_PUBLIC_SESSION_HEADER = "x-lotics-app-session";
|
|
162
172
|
/**
|
|
163
173
|
* The error message for a non-ok response. A genuine JSON error (a 4xx carrying
|
|
164
174
|
* a `message`) surfaces verbatim; a non-JSON body (a gateway HTML page), any
|
package/dist/src/rpc.js
CHANGED
|
@@ -250,7 +250,7 @@ export function rpcAgentRunContinue(payload, onText) {
|
|
|
250
250
|
const { app_id } = await boot();
|
|
251
251
|
const headers = { "content-type": "application/json" };
|
|
252
252
|
if (sessionToken)
|
|
253
|
-
headers[
|
|
253
|
+
headers[APP_PUBLIC_SESSION_HEADER] = sessionToken;
|
|
254
254
|
const res = await fetch(`${API_BASE}/v1/apps/${app_id}/agent-runs/${encodeURIComponent(payload.run_id)}/continue`, {
|
|
255
255
|
method: "POST",
|
|
256
256
|
headers,
|
|
@@ -288,7 +288,7 @@ function agentRunStandalone(payload, onText, onRunId) {
|
|
|
288
288
|
const { app_id } = await boot();
|
|
289
289
|
const headers = { "content-type": "application/json" };
|
|
290
290
|
if (sessionToken)
|
|
291
|
-
headers[
|
|
291
|
+
headers[APP_PUBLIC_SESSION_HEADER] = sessionToken;
|
|
292
292
|
const res = await fetch(`${API_BASE}/v1/apps/${app_id}/agents/${encodeURIComponent(payload.alias)}/runs`, {
|
|
293
293
|
method: "POST",
|
|
294
294
|
headers,
|
|
@@ -336,6 +336,16 @@ const PASSWORD_REQUIRED_CODE = "PASSWORD_REQUIRED";
|
|
|
336
336
|
let bootPromise = null;
|
|
337
337
|
let appInfoPromise = null;
|
|
338
338
|
let sessionToken = null;
|
|
339
|
+
/**
|
|
340
|
+
* The password-session header. It is deliberately NOT `Authorization`: this
|
|
341
|
+
* token authenticates nobody — it proves the visitor knows the app's shared
|
|
342
|
+
* link password — and the credential header already carries API keys and OAuth
|
|
343
|
+
* bearers. Sharing it meant the server's auth middleware rejected the request
|
|
344
|
+
* as an unknown bearer before the password gate ever ran, which took every
|
|
345
|
+
* password-gated public app offline. Wire constant, mirrored server-side by
|
|
346
|
+
* `APP_PUBLIC_SESSION_HEADER`; both sides are pinned by tests.
|
|
347
|
+
*/
|
|
348
|
+
export const APP_PUBLIC_SESSION_HEADER = "x-lotics-app-session";
|
|
339
349
|
function sessionStorageKey(appId) {
|
|
340
350
|
return `lotics_app_session:${appId}`;
|
|
341
351
|
}
|
|
@@ -478,7 +488,7 @@ async function apiCall(method, path, body, opts) {
|
|
|
478
488
|
if (body)
|
|
479
489
|
headers["content-type"] = "application/json";
|
|
480
490
|
if (sessionToken && !opts?.skipAuth) {
|
|
481
|
-
headers[
|
|
491
|
+
headers[APP_PUBLIC_SESSION_HEADER] = sessionToken;
|
|
482
492
|
}
|
|
483
493
|
const controller = new AbortController();
|
|
484
494
|
let didTimeout = false;
|
package/docs/runtime.md
CHANGED
|
@@ -132,8 +132,12 @@ coalesce; a transient failure isn't cached, the next call retries). If the app
|
|
|
132
132
|
is password-protected, the SDK renders its own full-screen password overlay
|
|
133
133
|
(plain DOM, so it works before React data arrives), exchanges the password for a
|
|
134
134
|
session token, and stores it in `localStorage` under
|
|
135
|
-
`lotics_app_session:<app_id>` with its expiry. The token rides
|
|
136
|
-
|
|
135
|
+
`lotics_app_session:<app_id>` with its expiry. The token rides on subsequent
|
|
136
|
+
calls in its own `X-Lotics-App-Session` header — deliberately not
|
|
137
|
+
`Authorization`, which carries API keys and OAuth bearers: this token
|
|
138
|
+
authenticates nobody, it proves the visitor knows the shared password, and
|
|
139
|
+
sharing the credential header made the auth layer reject it before the password
|
|
140
|
+
gate could read it. A `401` with error code `PASSWORD_REQUIRED` (the
|
|
137
141
|
owner rotated or cleared the password) drops the stored token, re-prompts, and
|
|
138
142
|
retries the original call once. There is no cancel button — the visitor enters
|
|
139
143
|
the password or leaves. When `localStorage` is unavailable (private browsing,
|