@astram/frontend-core 0.11.0 → 0.12.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/agent/agentReducer.d.ts +27 -0
- package/dist/agent/agentReducer.d.ts.map +1 -0
- package/dist/agent/agentReducer.js +286 -0
- package/dist/agent/agentReducer.js.map +1 -0
- package/dist/agent/agentService.d.ts +136 -0
- package/dist/agent/agentService.d.ts.map +1 -0
- package/dist/agent/agentService.js +308 -0
- package/dist/agent/agentService.js.map +1 -0
- package/dist/agent/index.d.ts +14 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +10 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/scriptedTransport.d.ts +20 -0
- package/dist/agent/scriptedTransport.d.ts.map +1 -0
- package/dist/agent/scriptedTransport.js +122 -0
- package/dist/agent/scriptedTransport.js.map +1 -0
- package/dist/agent/sseParser.d.ts +45 -0
- package/dist/agent/sseParser.d.ts.map +1 -0
- package/dist/agent/sseParser.js +216 -0
- package/dist/agent/sseParser.js.map +1 -0
- package/dist/agent/types.d.ts +201 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/returnPath.d.ts +13 -1
- package/dist/auth/returnPath.d.ts.map +1 -1
- package/dist/auth/returnPath.js +74 -11
- package/dist/auth/returnPath.js.map +1 -1
- package/dist/http/refreshingHttp.d.ts +28 -1
- package/dist/http/refreshingHttp.d.ts.map +1 -1
- package/dist/http/refreshingHttp.js +19 -0
- package/dist/http/refreshingHttp.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/** `^task_[A-Za-z0-9_-]{22}$` (§3, M0 §10 H). */
|
|
2
|
+
const TASK_ID = /^task_[A-Za-z0-9_-]{22}$/;
|
|
3
|
+
/** The heartbeat comment the gateway writes every 15 s (§3 B). */
|
|
4
|
+
export const SSE_HEARTBEAT = ': hb\n\n';
|
|
5
|
+
/**
|
|
6
|
+
* The §3 B frame for one envelope, exactly as the gateway writes it (the SSE fixtures are stored
|
|
7
|
+
* as envelopes; their frames are derived with this rule). Used by the scripted transport.
|
|
8
|
+
*/
|
|
9
|
+
export function toSseFrame(event) {
|
|
10
|
+
const id = event.type === 'replay.truncated' ? '' : `id: ${event.seq}\n`;
|
|
11
|
+
return `${id}event: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`;
|
|
12
|
+
}
|
|
13
|
+
function isPlainObject(v) {
|
|
14
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
15
|
+
}
|
|
16
|
+
/** Create a parser for ONE stream (open, continue or replay). */
|
|
17
|
+
export function parseSseFrames(options = {}) {
|
|
18
|
+
const dropped = [];
|
|
19
|
+
let taskId = null;
|
|
20
|
+
let lastSeq = null;
|
|
21
|
+
let accepted = 0;
|
|
22
|
+
// Line assembly across chunks.
|
|
23
|
+
let pending = '';
|
|
24
|
+
let pendingCR = false;
|
|
25
|
+
let started = false;
|
|
26
|
+
let ended = false;
|
|
27
|
+
// The frame being collected.
|
|
28
|
+
let dataLines = [];
|
|
29
|
+
let eventType = '';
|
|
30
|
+
let frameId = null;
|
|
31
|
+
const drop = (reason, seq) => {
|
|
32
|
+
const d = { reason, seq };
|
|
33
|
+
dropped.push(d);
|
|
34
|
+
try {
|
|
35
|
+
options.onDrop?.(d);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
/* reporting is best-effort */
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const check = (data, type, id) => {
|
|
42
|
+
let raw;
|
|
43
|
+
try {
|
|
44
|
+
raw = JSON.parse(data);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
drop('malformed', null);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
if (!isPlainObject(raw)) {
|
|
51
|
+
drop('malformed', null);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const seq = Number.isSafeInteger(raw.seq) ? raw.seq : null;
|
|
55
|
+
const truncated = raw.type === 'replay.truncated';
|
|
56
|
+
if (raw.v !== 0 ||
|
|
57
|
+
seq === null ||
|
|
58
|
+
seq < (truncated ? 0 : 1) ||
|
|
59
|
+
typeof raw.taskId !== 'string' ||
|
|
60
|
+
!TASK_ID.test(raw.taskId) ||
|
|
61
|
+
typeof raw.type !== 'string' ||
|
|
62
|
+
raw.type === '' ||
|
|
63
|
+
typeof raw.ts !== 'string' ||
|
|
64
|
+
!isPlainObject(raw.payload)) {
|
|
65
|
+
drop('malformed', seq);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
if (raw.type !== type) {
|
|
69
|
+
drop('type_mismatch', seq);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
if (truncated) {
|
|
73
|
+
const first = raw.payload.firstRetainedSeq;
|
|
74
|
+
if (!Number.isSafeInteger(first) || first < 1 || seq !== first - 1) {
|
|
75
|
+
drop('malformed', seq);
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
if (id !== null) {
|
|
79
|
+
drop('id_mismatch', seq);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
if (accepted > 0) {
|
|
83
|
+
drop('seq', seq);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (id !== String(seq)) {
|
|
88
|
+
drop('id_mismatch', seq);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
if (taskId !== null && raw.taskId !== taskId) {
|
|
92
|
+
drop('task_mismatch', seq);
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
if (lastSeq !== null && seq !== lastSeq + 1) {
|
|
96
|
+
drop('seq', seq);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
taskId = raw.taskId;
|
|
100
|
+
lastSeq = seq;
|
|
101
|
+
accepted += 1;
|
|
102
|
+
return {
|
|
103
|
+
v: 0,
|
|
104
|
+
seq,
|
|
105
|
+
taskId: raw.taskId,
|
|
106
|
+
type: raw.type,
|
|
107
|
+
ts: raw.ts,
|
|
108
|
+
payload: raw.payload,
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
const dispatch = (out) => {
|
|
112
|
+
const lines = dataLines;
|
|
113
|
+
const type = eventType === '' ? 'message' : eventType;
|
|
114
|
+
const id = frameId;
|
|
115
|
+
dataLines = [];
|
|
116
|
+
eventType = '';
|
|
117
|
+
frameId = null;
|
|
118
|
+
if (lines.length === 0)
|
|
119
|
+
return; // no data ⇒ no event (SSE rule)
|
|
120
|
+
const event = check(lines.join('\n'), type, id);
|
|
121
|
+
if (event)
|
|
122
|
+
out.push(event);
|
|
123
|
+
};
|
|
124
|
+
const line = (text, out) => {
|
|
125
|
+
if (text === '') {
|
|
126
|
+
dispatch(out);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (text.startsWith(':'))
|
|
130
|
+
return; // comment (heartbeat)
|
|
131
|
+
const colon = text.indexOf(':');
|
|
132
|
+
const field = colon < 0 ? text : text.slice(0, colon);
|
|
133
|
+
let value = colon < 0 ? '' : text.slice(colon + 1);
|
|
134
|
+
if (value.startsWith(' '))
|
|
135
|
+
value = value.slice(1);
|
|
136
|
+
switch (field) {
|
|
137
|
+
case 'data':
|
|
138
|
+
dataLines.push(value);
|
|
139
|
+
break;
|
|
140
|
+
case 'event':
|
|
141
|
+
eventType = value;
|
|
142
|
+
break;
|
|
143
|
+
case 'id':
|
|
144
|
+
if (!value.includes('\u0000'))
|
|
145
|
+
frameId = value;
|
|
146
|
+
break;
|
|
147
|
+
default:
|
|
148
|
+
break; // `retry` and unknown fields are ignored
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
return {
|
|
152
|
+
push(text) {
|
|
153
|
+
const out = [];
|
|
154
|
+
if (ended || typeof text !== 'string' || text.length === 0)
|
|
155
|
+
return out;
|
|
156
|
+
let s = text;
|
|
157
|
+
if (!started) {
|
|
158
|
+
started = true;
|
|
159
|
+
if (s.charCodeAt(0) === 0xfeff)
|
|
160
|
+
s = s.slice(1);
|
|
161
|
+
}
|
|
162
|
+
let i = 0;
|
|
163
|
+
if (pendingCR) {
|
|
164
|
+
pendingCR = false;
|
|
165
|
+
if (s.charCodeAt(0) === 0x0a)
|
|
166
|
+
i = 1; // the LF of a CRLF split across chunks
|
|
167
|
+
}
|
|
168
|
+
while (i < s.length) {
|
|
169
|
+
let j = i;
|
|
170
|
+
while (j < s.length) {
|
|
171
|
+
const c = s.charCodeAt(j);
|
|
172
|
+
if (c === 0x0a || c === 0x0d)
|
|
173
|
+
break;
|
|
174
|
+
j += 1;
|
|
175
|
+
}
|
|
176
|
+
if (j === s.length) {
|
|
177
|
+
pending += s.slice(i);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
const text = pending + s.slice(i, j);
|
|
181
|
+
pending = '';
|
|
182
|
+
if (s.charCodeAt(j) === 0x0d) {
|
|
183
|
+
if (j + 1 < s.length) {
|
|
184
|
+
if (s.charCodeAt(j + 1) === 0x0a)
|
|
185
|
+
j += 1;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
pendingCR = true;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
line(text, out);
|
|
192
|
+
i = j + 1;
|
|
193
|
+
}
|
|
194
|
+
return out;
|
|
195
|
+
},
|
|
196
|
+
end() {
|
|
197
|
+
ended = true;
|
|
198
|
+
pending = '';
|
|
199
|
+
pendingCR = false;
|
|
200
|
+
dataLines = [];
|
|
201
|
+
eventType = '';
|
|
202
|
+
frameId = null;
|
|
203
|
+
return [];
|
|
204
|
+
},
|
|
205
|
+
get dropped() {
|
|
206
|
+
return dropped;
|
|
207
|
+
},
|
|
208
|
+
get taskId() {
|
|
209
|
+
return taskId;
|
|
210
|
+
},
|
|
211
|
+
get lastSeq() {
|
|
212
|
+
return lastSeq;
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=sseParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sseParser.js","sourceRoot":"","sources":["../../src/agent/sseParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types of the agent client (G-036 M1, SPEC `docs/features/agent-read-capabilities/SPEC.md`
|
|
3
|
+
* §3 B–F, §5 frontend-core). DOM-free: the stream transport is injected (web: `fetch` with a
|
|
4
|
+
* streamed body, in the scaffolded app), so nothing here names `fetch`, `EventSource` or a DOM type.
|
|
5
|
+
*
|
|
6
|
+
* Model text (`answer`, `claims[].text`, `gaps`, question and option text) is plain text: render
|
|
7
|
+
* it as text, never as HTML or Markdown-to-HTML. Ids (`taskId`, `callId`) are opaque: never show them.
|
|
8
|
+
*/
|
|
9
|
+
import type { AbortSignalLike } from '../http/types.js';
|
|
10
|
+
/** The gateway stream contract version (§3 B, Q12). */
|
|
11
|
+
export declare const AGENT_STREAM_VERSION = 0;
|
|
12
|
+
/** No event and no heartbeat for this long ⇒ the stream is treated as lost (§5 frontend-core). */
|
|
13
|
+
export declare const AGENT_STREAM_STALL_MS = 45000;
|
|
14
|
+
/** Event types the gateway emits in M1 (§3 B). Reserved types may arrive later and are ignored. */
|
|
15
|
+
export type AgentEventType = 'task.started' | 'step' | 'tool.started' | 'tool.finished' | 'clarification.required' | 'answer' | 'done' | 'error' | 'replay.truncated';
|
|
16
|
+
/**
|
|
17
|
+
* One event as sent on the stream (the frozen §3 B envelope). `payload` is passed on as received
|
|
18
|
+
* and read defensively by the reducer.
|
|
19
|
+
*/
|
|
20
|
+
export interface AgentStreamEvent {
|
|
21
|
+
readonly v: 0;
|
|
22
|
+
readonly seq: number;
|
|
23
|
+
readonly taskId: string;
|
|
24
|
+
/** One of {@link AgentEventType}, or a type a later gateway adds (ignored by the reducer). */
|
|
25
|
+
readonly type: string;
|
|
26
|
+
readonly ts: string;
|
|
27
|
+
readonly payload: Readonly<Record<string, unknown>>;
|
|
28
|
+
}
|
|
29
|
+
/** Why the parser refused a frame (it is dropped and reported, never applied). */
|
|
30
|
+
export type SseDropReason =
|
|
31
|
+
/** Not JSON, not the §3 B envelope, or a bad `replay.truncated`. */
|
|
32
|
+
'malformed'
|
|
33
|
+
/** `taskId` differs from the stream's first event. */
|
|
34
|
+
| 'task_mismatch'
|
|
35
|
+
/** `seq` is not the next one (or a `replay.truncated` that is not the first event). */
|
|
36
|
+
| 'seq'
|
|
37
|
+
/** The `id:` line disagrees with the envelope `seq`, or is missing where one is required. */
|
|
38
|
+
| 'id_mismatch'
|
|
39
|
+
/** The `event:` line disagrees with the envelope `type`. */
|
|
40
|
+
| 'type_mismatch';
|
|
41
|
+
/** A refused frame. Carries no frame text (it may hold model text). */
|
|
42
|
+
export interface SseDrop {
|
|
43
|
+
readonly reason: SseDropReason;
|
|
44
|
+
/** The envelope `seq` when it could be read, else null. */
|
|
45
|
+
readonly seq: number | null;
|
|
46
|
+
}
|
|
47
|
+
/** `Num` of the evidence kinds: a JSON number, an exact decimal string (never re-parsed), or null. */
|
|
48
|
+
export type EvidenceNum = number | string | null;
|
|
49
|
+
export interface MetricEvidence {
|
|
50
|
+
readonly kind: 'metric';
|
|
51
|
+
readonly label: string;
|
|
52
|
+
readonly value: EvidenceNum;
|
|
53
|
+
readonly unit?: string;
|
|
54
|
+
readonly asOf?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface TableEvidence {
|
|
57
|
+
readonly kind: 'table';
|
|
58
|
+
readonly columns: readonly {
|
|
59
|
+
readonly key: string;
|
|
60
|
+
readonly label: string;
|
|
61
|
+
readonly numeric?: boolean;
|
|
62
|
+
}[];
|
|
63
|
+
readonly rows: readonly Readonly<Record<string, string | number | boolean | null>>[];
|
|
64
|
+
}
|
|
65
|
+
export interface SeriesEvidence {
|
|
66
|
+
readonly kind: 'series';
|
|
67
|
+
readonly label: string;
|
|
68
|
+
readonly unit?: string;
|
|
69
|
+
readonly points: readonly {
|
|
70
|
+
readonly x: string;
|
|
71
|
+
readonly y: EvidenceNum;
|
|
72
|
+
}[];
|
|
73
|
+
}
|
|
74
|
+
/** Evidence for the UI (§5 E). Decimal strings are kept as strings: format, never `parseFloat`. */
|
|
75
|
+
export type AgentEvidence = MetricEvidence | TableEvidence | SeriesEvidence;
|
|
76
|
+
/** A partial read: `shown` of `total` (`total: null` = more exist, count unknown). */
|
|
77
|
+
export interface AgentPartial {
|
|
78
|
+
readonly shown: number;
|
|
79
|
+
readonly total: number | null;
|
|
80
|
+
}
|
|
81
|
+
/** `running` until `tool.finished`; then the M0 §10 C result status. */
|
|
82
|
+
export type AgentToolStatus = 'running' | 'ok' | 'denied' | 'invalid' | 'failed' | 'timeout';
|
|
83
|
+
export interface AgentToolState {
|
|
84
|
+
/** `id@version`; null when the `tool.started` event was not received (truncated replay). */
|
|
85
|
+
readonly capability: string | null;
|
|
86
|
+
/** Display title from the server registry; null as above. */
|
|
87
|
+
readonly title: string | null;
|
|
88
|
+
readonly status: AgentToolStatus;
|
|
89
|
+
readonly code: string | null;
|
|
90
|
+
readonly evidence: AgentEvidence | null;
|
|
91
|
+
readonly partial: AgentPartial | null;
|
|
92
|
+
}
|
|
93
|
+
export interface AgentStep {
|
|
94
|
+
readonly key: string;
|
|
95
|
+
/** Fixed server label (never model text). */
|
|
96
|
+
readonly label: string;
|
|
97
|
+
}
|
|
98
|
+
export interface AgentClaim {
|
|
99
|
+
readonly text: string;
|
|
100
|
+
/** `callId`s of `ok` results backing the claim. */
|
|
101
|
+
readonly refs: readonly string[];
|
|
102
|
+
}
|
|
103
|
+
export interface AgentAnswer {
|
|
104
|
+
readonly answer: string;
|
|
105
|
+
readonly claims: readonly AgentClaim[];
|
|
106
|
+
readonly gaps: readonly string[];
|
|
107
|
+
}
|
|
108
|
+
export interface AgentQuestionOption {
|
|
109
|
+
readonly value: string;
|
|
110
|
+
readonly label: string;
|
|
111
|
+
}
|
|
112
|
+
/** A clarification question (M0 §10 J shape). `options` only for `single` and `multi`. */
|
|
113
|
+
export interface AgentQuestion {
|
|
114
|
+
readonly id: string;
|
|
115
|
+
readonly text: string;
|
|
116
|
+
readonly kind: 'single' | 'multi' | 'free_text';
|
|
117
|
+
readonly options?: readonly AgentQuestionOption[];
|
|
118
|
+
}
|
|
119
|
+
/** The task's error: an SSE `error`, a refusal before the stream, or the client's `connection_lost`. */
|
|
120
|
+
export interface AgentTaskError {
|
|
121
|
+
readonly code: string;
|
|
122
|
+
readonly retryable: boolean;
|
|
123
|
+
/** Fixed text for the code (never server text). */
|
|
124
|
+
readonly message: string;
|
|
125
|
+
}
|
|
126
|
+
export interface AgentUsage {
|
|
127
|
+
readonly modelCalls: number;
|
|
128
|
+
readonly toolCalls: number;
|
|
129
|
+
}
|
|
130
|
+
export type AgentTaskStatus = 'idle' | 'streaming' | 'awaiting_clarification' | 'done' | 'error';
|
|
131
|
+
/**
|
|
132
|
+
* The reducer state (§5 frontend-core). It shows the latest run of the task: `task.started`
|
|
133
|
+
* clears the run-scoped parts (steps, tools, answer, questions, error, usage).
|
|
134
|
+
*/
|
|
135
|
+
export interface AgentTaskState {
|
|
136
|
+
readonly taskId: string | null;
|
|
137
|
+
readonly status: AgentTaskStatus;
|
|
138
|
+
/** The run number from the last `task.started` (0 before one). */
|
|
139
|
+
readonly run: number;
|
|
140
|
+
readonly steps: readonly AgentStep[];
|
|
141
|
+
readonly tools: Readonly<Record<string, AgentToolState>>;
|
|
142
|
+
readonly answer: AgentAnswer | null;
|
|
143
|
+
readonly questions: readonly AgentQuestion[] | null;
|
|
144
|
+
readonly error: AgentTaskError | null;
|
|
145
|
+
/** The run's counts from `done`. */
|
|
146
|
+
readonly usage: AgentUsage | null;
|
|
147
|
+
/** The highest `seq` applied (0 = none). Pass it to `replay` to fetch what came after. */
|
|
148
|
+
readonly lastSeq: number;
|
|
149
|
+
/** `true` while a live stream (open or continue) is connected. */
|
|
150
|
+
readonly live: boolean;
|
|
151
|
+
/** `true` once events of this task were missed (a `replay.truncated`, or a `seq` gap). */
|
|
152
|
+
readonly truncated: boolean;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Client-side inputs to the reducer: stream lifecycle and refusals. Not sent by the server; the
|
|
156
|
+
* `local.` prefix cannot collide with a gateway type.
|
|
157
|
+
*/
|
|
158
|
+
export type AgentLocalEvent = {
|
|
159
|
+
readonly type: 'local.opened';
|
|
160
|
+
readonly live: boolean;
|
|
161
|
+
} | {
|
|
162
|
+
readonly type: 'local.closed';
|
|
163
|
+
} | {
|
|
164
|
+
readonly type: 'local.connection_lost';
|
|
165
|
+
} | {
|
|
166
|
+
readonly type: 'local.refused';
|
|
167
|
+
readonly status: number;
|
|
168
|
+
readonly code: string | null;
|
|
169
|
+
readonly retryable: boolean;
|
|
170
|
+
};
|
|
171
|
+
/** The parsed §3 D body of a refusal before the first stream byte. */
|
|
172
|
+
export interface AgentRefusalBody {
|
|
173
|
+
readonly code: string;
|
|
174
|
+
readonly retryable: boolean;
|
|
175
|
+
}
|
|
176
|
+
/** One request to the stream transport (§5 frontend-core). */
|
|
177
|
+
export interface AgentStreamRequest {
|
|
178
|
+
readonly method: 'POST' | 'GET';
|
|
179
|
+
/** Path under the API base, e.g. `/agent/tasks`. */
|
|
180
|
+
readonly path: string;
|
|
181
|
+
/** JSON body for POST; null for GET. */
|
|
182
|
+
readonly body: unknown | null;
|
|
183
|
+
/** `Last-Event-ID` for a replay (`GET …/events`). */
|
|
184
|
+
readonly lastEventId?: number;
|
|
185
|
+
readonly signal: AbortSignalLike;
|
|
186
|
+
}
|
|
187
|
+
/** What the transport answers. `chunks` only with `status` 200; network failure ⇒ `status: 0`. */
|
|
188
|
+
export interface AgentStreamResponse {
|
|
189
|
+
readonly status: number;
|
|
190
|
+
readonly error: AgentRefusalBody | null;
|
|
191
|
+
readonly chunks: AsyncIterable<string> | null;
|
|
192
|
+
close(): void;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The injected stream transport (web: `fetch` with a streamed body, never `EventSource`). It owns
|
|
196
|
+
* authentication of the stream request; a refresh is allowed only before the first byte.
|
|
197
|
+
*/
|
|
198
|
+
export interface AgentStreamTransport {
|
|
199
|
+
open(req: AgentStreamRequest): Promise<AgentStreamResponse>;
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The gateway stream contract version (§3 B, Q12). */
|
|
2
|
+
export const AGENT_STREAM_VERSION = 0;
|
|
3
|
+
/** No event and no heartbeat for this long ⇒ the stream is treated as lost (§5 frontend-core). */
|
|
4
|
+
export const AGENT_STREAM_STALL_MS = 45_000;
|
|
5
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AAUA,uDAAuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC,kGAAkG;AAClG,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC"}
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -26,5 +26,5 @@ export type { RecordShareService, ShareRequest, ShareView, ShareGranteeKind, } f
|
|
|
26
26
|
export { createServiceAccountService } from './serviceAccountService.js';
|
|
27
27
|
export type { ServiceAccountService, ServiceAccountView, IssuedKey, CreateServiceAccountBody, UpdateServiceAccountBody, AssignableAccess, AssignableRole, AssignableScopeNode, AssignableResult, KeyExpiry, } from './serviceAccountService.js';
|
|
28
28
|
export { isAuthenticated, accessTokenOf, tenantOf, principalOf } from './session.js';
|
|
29
|
-
export { isRestorablePath, encodeReturnPath, decodeReturnPath } from './returnPath.js';
|
|
29
|
+
export { isRestorablePath, encodeReturnPath, decodeReturnPath, safeReturnPath, } from './returnPath.js';
|
|
30
30
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,WAAW,EACX,cAAc,EACd,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,EAC3B,iCAAiC,GAClC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,SAAS,EACT,wBAAwB,EACxB,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,SAAS,GACV,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,WAAW,EACX,cAAc,EACd,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,wBAAwB,EACxB,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,EAC3B,iCAAiC,GAClC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,YAAY,EACV,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,SAAS,EACT,wBAAwB,EACxB,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,SAAS,GACV,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,GACf,MAAM,iBAAiB,CAAC"}
|
package/dist/auth/index.js
CHANGED
|
@@ -17,5 +17,5 @@ export { createRecordPolicyService } from './recordPolicyService.js';
|
|
|
17
17
|
export { createRecordShareService } from './recordShareService.js';
|
|
18
18
|
export { createServiceAccountService } from './serviceAccountService.js';
|
|
19
19
|
export { isAuthenticated, accessTokenOf, tenantOf, principalOf } from './session.js';
|
|
20
|
-
export { isRestorablePath, encodeReturnPath, decodeReturnPath } from './returnPath.js';
|
|
20
|
+
export { isRestorablePath, encodeReturnPath, decodeReturnPath, safeReturnPath, } from './returnPath.js';
|
|
21
21
|
//# sourceMappingURL=index.js.map
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAarD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAa7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAmBrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAazE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAUrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAOnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAazE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAarD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAa7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAmBrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAazE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAUrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAOnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAazE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,GACf,MAAM,iBAAiB,CAAC"}
|
|
@@ -9,7 +9,19 @@
|
|
|
9
9
|
* Obfuscation, not secrecy: the user owns their storage; the goal is "not human-readable".
|
|
10
10
|
*/
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* The same-origin in-app path `path` names, or null when it could leave the app.
|
|
13
|
+
*
|
|
14
|
+
* An allowlist, checked on the raw value and again after percent-decoding and dot-segment
|
|
15
|
+
* resolution: one leading `/`, then a character that is neither `/` nor `\`, printable ASCII
|
|
16
|
+
* only. So `//host`, `/\host`, any backslash, control characters, Unicode slash and backslash
|
|
17
|
+
* look-alikes, `%2F` / `%5C` before the query, `/.//host`, and absolute or scheme URLs are all
|
|
18
|
+
* refused. Returns the input unchanged when it is safe. Use it on every return target before
|
|
19
|
+
* navigating (a stored blob, router state, or a query parameter).
|
|
20
|
+
*/
|
|
21
|
+
export declare function safeReturnPath(path: unknown): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* True for real same-origin in-app routes; false for empty, root, off-origin paths
|
|
24
|
+
* (see `safeReturnPath`) and auth/transient pages.
|
|
13
25
|
*/
|
|
14
26
|
export declare function isRestorablePath(path: string | null | undefined): boolean;
|
|
15
27
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"returnPath.d.ts","sourceRoot":"","sources":["../../src/auth/returnPath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"returnPath.d.ts","sourceRoot":"","sources":["../../src/auth/returnPath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuFH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE3D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAQzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAS/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAY/E"}
|
package/dist/auth/returnPath.js
CHANGED
|
@@ -43,17 +43,82 @@ function fromBase64Url(s) {
|
|
|
43
43
|
b64 += '=';
|
|
44
44
|
return b64;
|
|
45
45
|
}
|
|
46
|
+
// The allowlist for the final pathname: one leading '/', then (if anything) a character that
|
|
47
|
+
// is neither '/', '\', a control character nor non-ASCII, then printable ASCII except '\'.
|
|
48
|
+
const SAFE_PATHNAME = /^\/(?:[\x20-\x2E\x30-\x5B\x5D-\x7E][\x20-\x5B\x5D-\x7E]*)?$/;
|
|
49
|
+
/** RFC 3986 §5.2.4 dot-segment removal for an absolute path (keeps empty segments). */
|
|
50
|
+
function removeDotSegments(absPath) {
|
|
51
|
+
const parts = absPath.split('/').slice(1);
|
|
52
|
+
const out = [];
|
|
53
|
+
parts.forEach((seg, i) => {
|
|
54
|
+
if (seg === '.' || seg === '..') {
|
|
55
|
+
if (seg === '..')
|
|
56
|
+
out.pop();
|
|
57
|
+
if (i === parts.length - 1)
|
|
58
|
+
out.push('');
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
out.push(seg);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return '/' + out.join('/');
|
|
65
|
+
}
|
|
46
66
|
/**
|
|
47
|
-
*
|
|
67
|
+
* The pathname a router or browser finally acts on (percent-decoded, then dot segments
|
|
68
|
+
* resolved; no query or hash), or null when `path` is not a safe same-origin in-app path.
|
|
69
|
+
* No `URL` dependency: frontend-core runs where `URL` is missing or partial (React Native).
|
|
70
|
+
*/
|
|
71
|
+
function safePathname(path) {
|
|
72
|
+
if (typeof path !== 'string' || path.length === 0)
|
|
73
|
+
return null;
|
|
74
|
+
// Raw form: a leading '/', printable ASCII only (no tab, newline or other control character
|
|
75
|
+
// a URL parser would strip, no Unicode look-alike), no '//' or '/\' authority, no '\' at all.
|
|
76
|
+
if (!/^\/[\x20-\x7E]*$/.test(path))
|
|
77
|
+
return null;
|
|
78
|
+
if (path.startsWith('//') || path.includes('\\'))
|
|
79
|
+
return null;
|
|
80
|
+
const rawPathname = path.split(/[?#]/, 1)[0] ?? '';
|
|
81
|
+
// An encoded slash or backslash in the path could become a separator after a decode.
|
|
82
|
+
if (/%(2f|5c)/i.test(rawPathname))
|
|
83
|
+
return null;
|
|
84
|
+
let decoded;
|
|
85
|
+
try {
|
|
86
|
+
decoded = decodeURIComponent(rawPathname);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const normalised = removeDotSegments(decoded);
|
|
92
|
+
if (!SAFE_PATHNAME.test(normalised))
|
|
93
|
+
return null;
|
|
94
|
+
return normalised;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The same-origin in-app path `path` names, or null when it could leave the app.
|
|
98
|
+
*
|
|
99
|
+
* An allowlist, checked on the raw value and again after percent-decoding and dot-segment
|
|
100
|
+
* resolution: one leading `/`, then a character that is neither `/` nor `\`, printable ASCII
|
|
101
|
+
* only. So `//host`, `/\host`, any backslash, control characters, Unicode slash and backslash
|
|
102
|
+
* look-alikes, `%2F` / `%5C` before the query, `/.//host`, and absolute or scheme URLs are all
|
|
103
|
+
* refused. Returns the input unchanged when it is safe. Use it on every return target before
|
|
104
|
+
* navigating (a stored blob, router state, or a query parameter).
|
|
105
|
+
*/
|
|
106
|
+
export function safeReturnPath(path) {
|
|
107
|
+
return safePathname(path) === null ? null : path;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* True for real same-origin in-app routes; false for empty, root, off-origin paths
|
|
111
|
+
* (see `safeReturnPath`) and auth/transient pages.
|
|
48
112
|
*/
|
|
49
113
|
export function isRestorablePath(path) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
//
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
114
|
+
// Matched on the normalised pathname (no query or hash, percent-decoded, dot segments
|
|
115
|
+
// resolved, lower-cased like the router's matching), so /login#x, /login?x, /./login,
|
|
116
|
+
// /%6Cogin and /LOGIN are all refused.
|
|
117
|
+
const normalised = safePathname(path);
|
|
118
|
+
if (normalised === null || normalised === '/')
|
|
55
119
|
return false;
|
|
56
|
-
|
|
120
|
+
const bare = normalised.toLowerCase();
|
|
121
|
+
return !NON_RESTORABLE_PREFIXES.some((p) => bare === p || bare.startsWith(p + '/'));
|
|
57
122
|
}
|
|
58
123
|
/**
|
|
59
124
|
* Obfuscate `path` to an opaque blob, or null if non-restorable / btoa unavailable.
|
|
@@ -82,10 +147,8 @@ export function decodeReturnPath(blob) {
|
|
|
82
147
|
return null;
|
|
83
148
|
try {
|
|
84
149
|
const path = xor(atob(fromBase64Url(blob)));
|
|
85
|
-
// A tampered/corrupt blob can decode to arbitrary bytes; only
|
|
86
|
-
//
|
|
87
|
-
if (!/^\/[\x20-\x7E]*$/.test(path))
|
|
88
|
-
return null;
|
|
150
|
+
// A tampered/corrupt blob can decode to arbitrary bytes; isRestorablePath accepts only a
|
|
151
|
+
// same-origin in-app path (safeReturnPath) that is not an auth page.
|
|
89
152
|
return isRestorablePath(path) ? path : null;
|
|
90
153
|
}
|
|
91
154
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"returnPath.js","sourceRoot":"","sources":["../../src/auth/returnPath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,yDAAyD;AACzD,MAAM,OAAO,GAAG,kBAAkB,CAAC;AAEnC,mEAAmE;AACnE,MAAM,uBAAuB,GAAG;IAC9B,QAAQ;IACR,kBAAkB;IAClB,iBAAiB;IACjB,mBAAmB;CACpB,CAAC;AAEF,SAAS,OAAO;IACd,MAAM,CAAC,GAAG,UAAqE,CAAC;IAChF,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC;AAED,SAAS,OAAO;IACd,MAAM,CAAC,GAAG,UAAqE,CAAC;IAChF,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD,CAAC;AAED,gFAAgF;AAChF,kDAAkD;AAClD,SAAS,GAAG,CAAC,KAAa;IACxB,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,aAAa,CAAC,CAAS;IAC9B,IAAI,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,GAAG,IAAI,GAAG,CAAC;IACxC,OAAO,GAAG,CAAC;AACb,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"returnPath.js","sourceRoot":"","sources":["../../src/auth/returnPath.ts"],"names":[],"mappings":"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"}
|