@anchrd/intel-api 0.6.2 → 0.6.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.
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { reportUnexpectedError } from "../../shared/report-unexpected-error/report-unexpected-error.js";
|
|
2
3
|
const StoredToken = z.strictObject({
|
|
3
4
|
version: z.literal(1),
|
|
4
5
|
accessToken: z.string().min(1),
|
|
@@ -41,9 +42,16 @@ export function createPortalTokenStore(deps) {
|
|
|
41
42
|
const { version: _version, ...token } = parsed;
|
|
42
43
|
return token;
|
|
43
44
|
}
|
|
44
|
-
catch {
|
|
45
|
+
catch (error) {
|
|
45
46
|
// A row that no longer decrypts (rotated secret, tampering) is treated as absent so the
|
|
46
47
|
// user is asked to reconnect instead of hitting an opaque failure on every call.
|
|
48
|
+
// ⚠️ Absent and unreadable look identical from the outside — both end in the sign-in screen
|
|
49
|
+
// — but only one of them is a defect. Without this line the difference is unobservable, and
|
|
50
|
+
// a connection that disappears has no explanation anywhere (#97). The row is named by its
|
|
51
|
+
// length alone; the sealed value never goes near a log.
|
|
52
|
+
reportUnexpectedError(new Error(`portal token for a user did not decrypt (sealed length ${row.sealed.length})`, {
|
|
53
|
+
cause: error,
|
|
54
|
+
}));
|
|
47
55
|
return null;
|
|
48
56
|
}
|
|
49
57
|
},
|
package/dist/tools/tools.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IntelError } from "../shared/intel-error/intel-error.js";
|
|
2
|
+
import { reportUnexpectedError } from "../shared/report-unexpected-error/report-unexpected-error.js";
|
|
2
3
|
const CallTimeoutMs = 15_000;
|
|
3
4
|
const MaxTools = 1_000;
|
|
4
5
|
const MaxResultBytes = 1_000_000;
|
|
@@ -24,6 +25,11 @@ export function createTools(deps) {
|
|
|
24
25
|
return stored.accessToken;
|
|
25
26
|
const refreshed = stored.refreshToken ? await deps.refresh(stored) : null;
|
|
26
27
|
if (!refreshed) {
|
|
28
|
+
// Losing a connection is a visible event for the person and an invisible one for everybody
|
|
29
|
+
// else: the screen simply asks them to sign in again, and no trace says why. The two reasons
|
|
30
|
+
// need telling apart — a portal that issues no refresh token at all is a configuration
|
|
31
|
+
// problem, a refresh that gets rejected is a different one (#97).
|
|
32
|
+
reportUnexpectedError(new Error(`portal token dropped: ${stored.refreshToken ? "refresh was rejected" : "no refresh token was ever issued"}`));
|
|
27
33
|
// A token that cannot be renewed is dropped: leaving it would keep failing every call with a
|
|
28
34
|
// stale credential. The browser answers this by signing in silently again (#60); an MCP
|
|
29
35
|
// client sees the code and repeats its own authorization.
|