@inerrata-corporation/errata 2.0.0-dev.32 → 2.0.0-dev.33

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 (2) hide show
  1. package/errata.mjs +80 -20
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -20434,6 +20434,37 @@ async function postToken(fetchFn, tokenEndpoint, params, timeoutMs = 15e3) {
20434
20434
  clearTimeout(tid);
20435
20435
  }
20436
20436
  }
20437
+ async function registerOAuthClient(fetchFn, registrationEndpoint, p, timeoutMs = 15e3) {
20438
+ const ac = new AbortController();
20439
+ const tid = setTimeout(() => ac.abort(), timeoutMs);
20440
+ try {
20441
+ const res = await fetchFn(registrationEndpoint, {
20442
+ method: "POST",
20443
+ headers: {
20444
+ "content-type": "application/json",
20445
+ accept: "application/json"
20446
+ },
20447
+ body: JSON.stringify({
20448
+ redirect_uris: [p.redirectUri],
20449
+ token_endpoint_auth_method: "none",
20450
+ grant_types: ["authorization_code", "refresh_token"],
20451
+ response_types: ["code"],
20452
+ client_name: p.clientName ?? "errata daemon",
20453
+ scope: p.scope
20454
+ }),
20455
+ signal: ac.signal
20456
+ });
20457
+ if (!res.ok) {
20458
+ const text = await res.text();
20459
+ throw new Error(`client registration failed: HTTP ${res.status} ${text.slice(0, 200)}`);
20460
+ }
20461
+ const j = await res.json();
20462
+ if (!j.client_id) throw new Error("client registration returned no client_id");
20463
+ return { clientId: j.client_id };
20464
+ } finally {
20465
+ clearTimeout(tid);
20466
+ }
20467
+ }
20437
20468
  function exchangeAuthorizationCode(fetchFn, tokenEndpoint, p) {
20438
20469
  return postToken(fetchFn, tokenEndpoint, {
20439
20470
  grant_type: "authorization_code",
@@ -20921,6 +20952,7 @@ function defaultConfig() {
20921
20952
  accessToken: null,
20922
20953
  refreshToken: null,
20923
20954
  tokenEndpoint: null,
20955
+ oauthClientId: null,
20924
20956
  userId: null,
20925
20957
  email: null,
20926
20958
  consent: { sync: false, telemetry: false, contributePackages: false },
@@ -21189,7 +21221,7 @@ function authedCloudClient(cfg, opts = {}) {
21189
21221
  ...tokenEndpoint && cfg.refreshToken ? {
21190
21222
  refreshFn: (rt) => refreshAccessToken(opts.fetchFn ?? fetch, tokenEndpoint, {
21191
21223
  refreshToken: rt,
21192
- clientId: oauthClientId()
21224
+ clientId: cfg.oauthClientId ?? oauthClientId()
21193
21225
  }),
21194
21226
  // Persist the rotated tokens so the next process starts fresh.
21195
21227
  onTokens: (t) => {
@@ -41846,7 +41878,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
41846
41878
  }
41847
41879
 
41848
41880
  // src/engine.ts
41849
- var DAEMON_VERSION = true ? "2.0.0-dev.32" : "2.0.0-alpha.0";
41881
+ var DAEMON_VERSION = true ? "2.0.0-dev.33" : "2.0.0-alpha.0";
41850
41882
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
41851
41883
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
41852
41884
  var GIT_OP_MUTE_MS = 4e3;
@@ -43037,6 +43069,7 @@ async function startDaemon(opts) {
43037
43069
  merged.accessToken = null;
43038
43070
  merged.refreshToken = null;
43039
43071
  merged.tokenEndpoint = null;
43072
+ merged.oauthClientId = null;
43040
43073
  }
43041
43074
  const cloud = authedCloudClient(merged);
43042
43075
  let webUiUrl = "";
@@ -43801,6 +43834,7 @@ async function startMultiDaemon(opts = {}) {
43801
43834
  initialCfg.accessToken = null;
43802
43835
  initialCfg.refreshToken = null;
43803
43836
  initialCfg.tokenEndpoint = null;
43837
+ initialCfg.oauthClientId = null;
43804
43838
  }
43805
43839
  const cloud = authedCloudClient(initialCfg, { timeoutMs: CLOUD_TIMEOUT_MS });
43806
43840
  const cloudNow = () => {
@@ -43812,6 +43846,7 @@ async function startMultiDaemon(opts = {}) {
43812
43846
  current.accessToken = null;
43813
43847
  current.refreshToken = null;
43814
43848
  current.tokenEndpoint = null;
43849
+ current.oauthClientId = null;
43815
43850
  }
43816
43851
  return authedCloudClient(current, { timeoutMs: CLOUD_TIMEOUT_MS });
43817
43852
  };
@@ -44424,6 +44459,7 @@ init_cloud_endpoint_policy();
44424
44459
  init_src6();
44425
44460
  init_cloud_auth();
44426
44461
  import { createServer } from "node:http";
44462
+ var DEFAULT_OAUTH_SCOPE = "openid profile graph:read graph:write mcp:tools";
44427
44463
  var strip = (u) => u.replace(/\/+$/, "");
44428
44464
  async function discoverEndpoints(cloudUrl, fetchFn = fetch) {
44429
44465
  let consoleUrl = cloudUrl;
@@ -44440,7 +44476,11 @@ async function discoverEndpoints(cloudUrl, fetchFn = fetch) {
44440
44476
  if (asm.ok) {
44441
44477
  const j = await asm.json();
44442
44478
  if (j.authorization_endpoint && j.token_endpoint) {
44443
- return { authorizationEndpoint: j.authorization_endpoint, tokenEndpoint: j.token_endpoint };
44479
+ return {
44480
+ authorizationEndpoint: j.authorization_endpoint,
44481
+ tokenEndpoint: j.token_endpoint,
44482
+ ...j.registration_endpoint ? { registrationEndpoint: j.registration_endpoint } : {}
44483
+ };
44444
44484
  }
44445
44485
  }
44446
44486
  } catch {
@@ -44467,8 +44507,8 @@ async function loginOAuthLoopback(opts) {
44467
44507
  const endpoints = await discoverEndpoints(opts.cloudUrl, fetchFn);
44468
44508
  const pkce = generatePkce();
44469
44509
  const state = randomState();
44470
- const clientId = oauthClientId();
44471
- const { code, redirectUri } = await new Promise(
44510
+ const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
44511
+ const { code, redirectUri, clientId } = await new Promise(
44472
44512
  (resolve5, reject) => {
44473
44513
  const server = createServer((req, res) => {
44474
44514
  const u = new URL(req.url ?? "/", "http://127.0.0.1");
@@ -44492,24 +44532,40 @@ async function loginOAuthLoopback(opts) {
44492
44532
  res.writeHead(200, { "content-type": "text/html" });
44493
44533
  res.end("<html><body>inErrata: you're logged in. You can close this tab.</body></html>");
44494
44534
  server.close();
44495
- resolve5({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback` });
44535
+ resolve5({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
44496
44536
  });
44537
+ let activeClientId = oauthClientId();
44497
44538
  server.on("error", reject);
44498
44539
  server.listen(0, "127.0.0.1", () => {
44499
- const addr2 = server.address();
44500
- const port = typeof addr2 === "object" && addr2 ? addr2.port : 0;
44501
- const redirectUri2 = `http://127.0.0.1:${port}/callback`;
44502
- const url2 = buildAuthorizeUrl(endpoints.authorizationEndpoint, {
44503
- clientId,
44504
- redirectUri: redirectUri2,
44505
- scope: opts.scope ?? "openid profile",
44506
- state,
44507
- challenge: pkce.challenge,
44508
- method: pkce.method
44509
- });
44510
- if (opts.open) opts.open(url2);
44511
- else console.log(`approve this login in your browser:
44540
+ void (async () => {
44541
+ try {
44542
+ const addr2 = server.address();
44543
+ const port = typeof addr2 === "object" && addr2 ? addr2.port : 0;
44544
+ const redirectUri2 = `http://127.0.0.1:${port}/callback`;
44545
+ if (endpoints.registrationEndpoint) {
44546
+ const registered = await registerOAuthClient(fetchFn, endpoints.registrationEndpoint, {
44547
+ redirectUri: redirectUri2,
44548
+ scope,
44549
+ clientName: "errata daemon"
44550
+ });
44551
+ activeClientId = registered.clientId;
44552
+ }
44553
+ const url2 = buildAuthorizeUrl(endpoints.authorizationEndpoint, {
44554
+ clientId: activeClientId,
44555
+ redirectUri: redirectUri2,
44556
+ scope,
44557
+ state,
44558
+ challenge: pkce.challenge,
44559
+ method: pkce.method
44560
+ });
44561
+ if (opts.open) opts.open(url2);
44562
+ else console.log(`approve this login in your browser:
44512
44563
  ${url2}`);
44564
+ } catch (err2) {
44565
+ server.close();
44566
+ reject(err2);
44567
+ }
44568
+ })();
44513
44569
  });
44514
44570
  if (opts.timeoutMs) {
44515
44571
  setTimeout(() => {
@@ -44525,7 +44581,7 @@ async function loginOAuthLoopback(opts) {
44525
44581
  redirectUri,
44526
44582
  clientId
44527
44583
  });
44528
- return { tokens, tokenEndpoint: endpoints.tokenEndpoint };
44584
+ return { tokens, tokenEndpoint: endpoints.tokenEndpoint, clientId };
44529
44585
  }
44530
44586
 
44531
44587
  // src/update.ts
@@ -45117,6 +45173,7 @@ async function applyToken(cfg, token) {
45117
45173
  cfg.accessToken = null;
45118
45174
  cfg.refreshToken = null;
45119
45175
  cfg.tokenEndpoint = null;
45176
+ cfg.oauthClientId = null;
45120
45177
  cfg.userId = me.agentId;
45121
45178
  cfg.email = me.handle;
45122
45179
  saveConfig(cfg);
@@ -45161,6 +45218,7 @@ async function cmdLoginOAuth(cfg) {
45161
45218
  cfg.accessToken = result.tokens.accessToken;
45162
45219
  cfg.refreshToken = result.tokens.refreshToken ?? null;
45163
45220
  cfg.tokenEndpoint = result.tokenEndpoint;
45221
+ cfg.oauthClientId = result.clientId;
45164
45222
  cfg.apiKey = null;
45165
45223
  saveConfig(cfg);
45166
45224
  try {
@@ -45232,6 +45290,7 @@ async function cmdLogin() {
45232
45290
  cfg.accessToken = null;
45233
45291
  cfg.refreshToken = null;
45234
45292
  cfg.tokenEndpoint = null;
45293
+ cfg.oauthClientId = null;
45235
45294
  cfg.userId = poll.agentId ?? null;
45236
45295
  cfg.email = poll.handle ?? handle2;
45237
45296
  saveConfig(cfg);
@@ -45259,6 +45318,7 @@ async function cmdLogout() {
45259
45318
  cfg.accessToken = null;
45260
45319
  cfg.refreshToken = null;
45261
45320
  cfg.tokenEndpoint = null;
45321
+ cfg.oauthClientId = null;
45262
45322
  cfg.userId = null;
45263
45323
  cfg.email = null;
45264
45324
  saveConfig(cfg);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.32",
3
+ "version": "2.0.0-dev.33",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {