@vymalo/opencode-lightbridge 0.19.0 → 0.20.0

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/opencode.js CHANGED
@@ -2,6 +2,7 @@ import { hostname } from "node:os";
2
2
  import { Plugin } from "@opencode/plugin/effect";
3
3
  import { defaultTextMapSetter } from "@opentelemetry/api";
4
4
  import { W3CTraceContextPropagator } from "@opentelemetry/core";
5
+ import { isInteractiveAuthRequiredError } from "@vymalo/opencode-auth-core/lib";
5
6
  import { buildResource, createProviders, deferredAttribute, describeError, readVcsInfo, registerExitHandlers, resolveOtelConfig, TelemetryRecorder } from "@vymalo/opencode-core-otel";
6
7
  import { applyResponsesApiSettings, mergeDiscoveredModels, propagateCachedBearer, ProviderModelSyncEngine, resolveCachedBearer, resolveProviderPackage, upsertManagedProvider } from "@vymalo/opencode-provider-sync/lib";
7
8
  import { Effect, Stream } from "effect";
@@ -9,6 +10,7 @@ import { hasOAuth2Conflict, needsProjectToken, parseLightbridgeOptions } from ".
9
10
  import { captureHostContext, createEffectLogger, DEFAULT_LOG_LEVEL, resolveLogLevel, runInHost } from "./logging.js";
10
11
  import { adaptContext, adaptPermission, adaptPrompt, adaptToolAfter, adaptToolBefore, OtelEventAdapter } from "./otel-adapter.js";
11
12
  import { LightbridgeRuntime, ROOT_CACHE_NAMESPACE, ROOT_CACHE_SEGMENT, rootCacheDir, rootStateDir } from "./plugin.js";
13
+ import { createSignInRegistration, createSignInRequiredNotifier, signInPath } from "./sign-in.js";
12
14
  /** Stable plugin id. v2 requires one and keys storage/registrations by it. */
13
15
  export const PLUGIN_ID = "vymalo.lightbridge";
14
16
  function errorMessage(error) {
@@ -36,13 +38,16 @@ function safeHostname() {
36
38
  * every export attempt, a later successful login resumes exporting on the
37
39
  * next flush with nothing to restart.
38
40
  */
39
- function createRuntimeTokenSource(runtime) {
41
+ function createRuntimeTokenSource(runtime, onSignInRequired) {
40
42
  return {
41
43
  headers: async () => {
42
44
  try {
43
- const token = await runtime.getProjectToken({ interactive: false });
45
+ const token = await runtime.getProjectToken();
44
46
  return { Authorization: `${token.tokenType || "Bearer"} ${token.accessToken}` };
45
- } catch {
47
+ } catch (error) {
48
+ if (isInteractiveAuthRequiredError(error)) {
49
+ onSignInRequired("otel");
50
+ }
46
51
  return undefined;
47
52
  }
48
53
  },
@@ -128,7 +133,7 @@ function warnIfTokenCommandConfigIgnored(otel, env, logger) {
128
133
  * handlers. Mirrors `@vymalo/opencode-otel`'s orchestration verbatim, minus
129
134
  * the standalone `tokenCommand` seam.
130
135
  */
131
- async function buildOtelModule(location, otelConfig, logger, factoryOptions, runtime) {
136
+ async function buildOtelModule(location, otelConfig, logger, factoryOptions, runtime, onSignInRequired) {
132
137
  const version = deferredAttribute(factoryOptions.deferredTimeoutMs);
133
138
  const branch = deferredAttribute(factoryOptions.deferredTimeoutMs);
134
139
  if (factoryOptions.hostInfo?.version) {
@@ -147,7 +152,7 @@ async function buildOtelModule(location, otelConfig, logger, factoryOptions, run
147
152
  branch: branch.value,
148
153
  vcs
149
154
  });
150
- const tokenSource = runtime ? createRuntimeTokenSource(runtime) : undefined;
155
+ const tokenSource = runtime ? createRuntimeTokenSource(runtime, onSignInRequired) : undefined;
151
156
  const providers = createProviders(otelConfig, resource, logger, factoryOptions.exporters, tokenSource);
152
157
  const recorder = new TelemetryRecorder({
153
158
  providers,
@@ -248,7 +253,10 @@ export function createLightbridgePlugin(factoryOptions = {}) {
248
253
  // and the OTEL token source below. `undefined` only for a register/auth-only
249
254
  // config.
250
255
  const buildRuntime = factoryOptions.runtimeFactory ?? ((auth, pid, options) => new LightbridgeRuntime(auth, pid, options));
251
- const sharedRuntime = wantsProjectToken ? buildRuntime(parsed.auth, parsed.projectId, {
256
+ // Built whenever a module needs a token OR the user must be able to sign in
257
+ // (device_code, ADR-0023): the sign-in method drives this same runtime.
258
+ const signInEnabled = parsed.auth.authFlow === "device_code";
259
+ const sharedRuntime = wantsProjectToken || signInEnabled ? buildRuntime(parsed.auth, parsed.projectId, {
252
260
  logger,
253
261
  fetchImpl: factoryOptions.fetchImpl,
254
262
  onAuthorizationUrl: factoryOptions.onAuthorizationUrl,
@@ -257,6 +265,16 @@ export function createLightbridgePlugin(factoryOptions = {}) {
257
265
  exchange: parsed.gateway?.exchange ?? false
258
266
  }) : undefined;
259
267
  const reloadProviders = () => runInHost(hostContext, ctx.provider.reload());
268
+ const signInName = parsed.register?.name ?? parsed.auth.id;
269
+ const signInNotice = createSignInRequiredNotifier(logger, signInName);
270
+ // Only meaningful when the Connect dialog can actually be used to fix it.
271
+ const notifySignInRequired = (source) => {
272
+ if (signInEnabled) {
273
+ signInNotice.notify(source);
274
+ }
275
+ };
276
+ // Set below when sign-in is registered; the gateway hook calls it (cached).
277
+ let observeConnectionCached = async () => {};
260
278
  // ---- register module (ADR-0017 requirement 1) ----
261
279
  let engine;
262
280
  let registerChain = Promise.resolve();
@@ -281,6 +299,9 @@ export function createLightbridgePlugin(factoryOptions = {}) {
281
299
  servers: [buildRegisterServerConfig(parsed.auth, register)],
282
300
  cacheNamespace: ROOT_CACHE_NAMESPACE
283
301
  }, {
302
+ // Sign-in happens only in the host's Connect dialog (ADR-0023): the
303
+ // engine's warmup, scheduler and token reads are refresh-only.
304
+ neverInteractive: true,
284
305
  logger,
285
306
  fetchImpl: factoryOptions.fetchImpl,
286
307
  onAuthorizationUrl: factoryOptions.onAuthorizationUrl,
@@ -301,6 +322,17 @@ export function createLightbridgePlugin(factoryOptions = {}) {
301
322
  }
302
323
  engine = next;
303
324
  registerBearer = await resolveCachedBearer(parsed.auth.id, next, logger);
325
+ if (registerBearer === undefined && sharedRuntime) {
326
+ // resolveCachedBearer swallows why; ask the runtime so only a genuine
327
+ // "needs sign-in" (not a network/IdP outage) raises the notice.
328
+ try {
329
+ await sharedRuntime.ensureRootToken();
330
+ } catch (error) {
331
+ if (isInteractiveAuthRequiredError(error)) {
332
+ notifySignInRequired("register");
333
+ }
334
+ }
335
+ }
304
336
  // Models and bearer are now known: ask the host to re-run transforms.
305
337
  await reloadProviders();
306
338
  };
@@ -355,6 +387,116 @@ export function createLightbridgePlugin(factoryOptions = {}) {
355
387
  }
356
388
  });
357
389
  }
390
+ // ---- sign-in (ADR-0023): the ONLY place an interactive login can start ----
391
+ if (signInEnabled && sharedRuntime) {
392
+ const runtime = sharedRuntime;
393
+ const afterSignIn = async () => {
394
+ try {
395
+ // Pick up the new credential in the register module's engine and
396
+ // refresh the stamped bearer, then ask the host to re-run transforms.
397
+ if (engine) {
398
+ await engine.syncServer(parsed.auth.id);
399
+ registerBearer = await resolveCachedBearer(parsed.auth.id, engine, logger);
400
+ }
401
+ } catch (error) {
402
+ logger.warn("lightbridge_sign_in_sync_failed", { error: errorMessage(error) });
403
+ }
404
+ try {
405
+ await reloadProviders();
406
+ } catch (error) {
407
+ logger.warn("lightbridge_sign_in_reload_failed", { error: errorMessage(error) });
408
+ }
409
+ };
410
+ const registration = createSignInRegistration({
411
+ integrationID: parsed.auth.id,
412
+ runtime,
413
+ logger,
414
+ afterSignIn,
415
+ onSignedIn: () => signInNotice.reset(),
416
+ onSignInRequired: notifySignInRequired
417
+ });
418
+ // The integration id is `auth.id`, never the well-known URL's: the host
419
+ // loads the well-known manifest with `credentials.at(-1)` of ITS
420
+ // integration, and an oauth credential there would freeze it (ADR-0023).
421
+ yield* ctx.integration.transform((editor) => {
422
+ editor.update(parsed.auth.id, (integration) => {
423
+ integration.name = signInName;
424
+ });
425
+ editor.method.update(registration);
426
+ });
427
+ // ---- host disconnect => sign out (ADR-0023) ----
428
+ // TRANSITION-based: only a connection we saw present in THIS process and
429
+ // that is then gone signs us out. A host with no credential at startup is
430
+ // normal (users who signed in before sign-in moved into the dialog have a
431
+ // token and no host credential) and must keep working.
432
+ let connectionSeen = false;
433
+ let signingOut = false;
434
+ let lastObservedAt = 0;
435
+ const OBSERVE_CACHE_MS = 5e3;
436
+ const signOut = async () => {
437
+ logger.info("lightbridge_signed_out_by_host", { integrationID: parsed.auth.id });
438
+ try {
439
+ await runtime.reset();
440
+ } catch (error) {
441
+ logger.warn("lightbridge_sign_out_reset_failed", { error: errorMessage(error) });
442
+ }
443
+ // The engine keeps its token in memory even when the file is gone:
444
+ // drop it, and let the next transform build a fresh (signed-out) one.
445
+ stopEngine();
446
+ registerQueued = false;
447
+ signInNotice.reset();
448
+ notifySignInRequired("disconnect");
449
+ try {
450
+ await reloadProviders();
451
+ } catch (error) {
452
+ logger.warn("lightbridge_sign_out_reload_failed", { error: errorMessage(error) });
453
+ }
454
+ };
455
+ const onConnection = async (present) => {
456
+ if (present) {
457
+ connectionSeen = true;
458
+ return;
459
+ }
460
+ if (!connectionSeen || signingOut) {
461
+ return;
462
+ }
463
+ connectionSeen = false;
464
+ signingOut = true;
465
+ try {
466
+ await signOut();
467
+ } finally {
468
+ signingOut = false;
469
+ }
470
+ };
471
+ const observeConnection = (force) => {
472
+ if (!force && Date.now() - lastObservedAt < OBSERVE_CACHE_MS) {
473
+ return Promise.resolve();
474
+ }
475
+ lastObservedAt = Date.now();
476
+ return runInHost(hostContext, ctx.integration.connection.active(parsed.auth.id).pipe(Effect.flatMap((info) => Effect.promise(() => onConnection(info !== undefined))), Effect.ignore));
477
+ };
478
+ observeConnectionCached = () => observeConnection(false);
479
+ yield* Effect.forkScoped(Stream.runForEach(ctx.event.subscribe({ types: [
480
+ "credential.updated",
481
+ "credential.switched",
482
+ "integration.updated"
483
+ ] }), () => Effect.promise(() => observeConnection(true))).pipe(Effect.tapError((error) => Effect.sync(() => logger.warn("lightbridge_connection_watch_failed", { error: errorMessage(error) }))), Effect.ignore));
484
+ void observeConnection(true);
485
+ // Report a missing sign-in once, up front, without any network on the
486
+ // signed-out path (a stored token may refresh, which is fine).
487
+ void runtime.ensureRootToken().catch((error) => {
488
+ if (isInteractiveAuthRequiredError(error)) {
489
+ notifySignInRequired("startup");
490
+ } else {
491
+ logger.debug("lightbridge_startup_token_check_failed", { error: errorMessage(error) });
492
+ }
493
+ });
494
+ } else if (parsed.auth.authFlow === "authorization_code") {
495
+ logger.warn("lightbridge_sign_in_unsupported_flow", {
496
+ authFlow: parsed.auth.authFlow,
497
+ message: `lightbridge signs in through the host's Connect dialog (${signInPath(signInName)}), which needs authFlow "device_code"`
498
+ });
499
+ }
358
500
  // ---- gateway module ----
359
501
  // `sharedRuntime` is always defined here: it is built whenever `gateway`
360
502
  // or `otel` is configured (`wantsProjectToken`).
@@ -376,7 +518,8 @@ export function createLightbridgePlugin(factoryOptions = {}) {
376
518
  }
377
519
  return Effect.tryPromise({
378
520
  try: async () => {
379
- const token = await runtime.getProjectToken({ interactive: true });
521
+ await observeConnectionCached();
522
+ const token = await runtime.getProjectToken();
380
523
  // Header names are case-insensitive: drop any variant already set
381
524
  // (a stamped record header, the placeholder key's, a lowercase copy).
382
525
  for (const key of Object.keys(event.headers)) {
@@ -388,10 +531,18 @@ export function createLightbridgePlugin(factoryOptions = {}) {
388
531
  logger.trace("lightbridge_gateway_bearer_injected", { providerId });
389
532
  },
390
533
  catch: (error) => error
391
- }).pipe(Effect.tapError((error) => Effect.sync(() => logger.warn("lightbridge_gateway_no_bearer", {
392
- providerId,
393
- error: errorMessage(error)
394
- }))), Effect.orDie);
534
+ }).pipe(Effect.tapError((error) => Effect.sync(() => {
535
+ const needsSignIn = isInteractiveAuthRequiredError(error);
536
+ // While signed out every request repeats this; the one-time
537
+ // lightbridge_sign_in_required warning already says what to do.
538
+ logger[needsSignIn && signInEnabled ? "debug" : "warn"]("lightbridge_gateway_no_bearer", {
539
+ providerId,
540
+ error: errorMessage(error)
541
+ });
542
+ if (needsSignIn) {
543
+ notifySignInRequired("gateway");
544
+ }
545
+ })), Effect.orDie);
395
546
  });
396
547
  }
397
548
  // ---- otel module ----
@@ -404,7 +555,7 @@ export function createLightbridgePlugin(factoryOptions = {}) {
404
555
  const built = yield* Effect.promise(() => buildOtelModule({
405
556
  directory: ctx.location.directory,
406
557
  projectId: ctx.location.project?.id
407
- }, otelConfig, logger, factoryOptions, sharedRuntime));
558
+ }, otelConfig, logger, factoryOptions, sharedRuntime, notifySignInRequired));
408
559
  otel = built;
409
560
  const { recorder } = built;
410
561
  const adapter = new OtelEventAdapter(recorder, factoryOptions.now);
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,gBAAgB;AAEzB,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC,SAAS,iCAAiC;AAE1C,SACE,eACA,iBACA,mBACA,eACA,aACA,sBACA,mBACA,yBAOK;AACP,SACE,2BACA,uBACA,uBACA,yBACA,qBACA,wBACA,6BAGK;AACP,SAAS,QAAQ,cAAc;AAE/B,SACE,mBACA,mBACA,+BAGK;AACP,SACE,oBACA,oBACA,mBAGA,iBACA,iBACK;AACP,SACE,cACA,iBACA,aACA,gBACA,iBAEA,wBACK;AACP,SACE,oBACA,sBACA,oBACA,cACA,oBAIK;;AAGP,OAAO,MAAM,YAAY;AA6CzB,SAAS,aAAa,OAAwB;CAC5C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,SAAS,eAAmC;CAC1C,IAAI;EACF,OAAO,SAAS,KAAK;CACvB,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;;;;;;;;;;AAiBA,SAAS,yBAAyB,SAA8C;CAC9E,OAAO;EACL,SAAS,YAAyD;GAChE,IAAI;IACF,MAAM,QAAQ,MAAM,QAAQ,gBAAgB,EAAE,aAAa,MAAM,CAAC;IAClE,OAAO,EAAE,eAAe,GAAG,MAAM,aAAa,SAAS,GAAG,MAAM,cAAc;GAChF,QAAQ;IACN,OAAO;GACT;EACF;;;;;EAKA,kBAAkB,CAAC;CACrB;AACF;;;;;;;;AASA,SAAS,0BACP,MACA,UACsB;CACtB,OAAO;EACL,IAAI,KAAK;EACT,MAAM,SAAS,QAAQ,KAAK;EAC5B,QAAQ,KAAK;EACb,SAAS,SAAS;EAClB,UAAU,KAAK;EACf,cAAc,KAAK;EACnB,QAAQ,KAAK;EACb,qBAAqB,SAAS,uBAAuB;EACrD,eAAe,SAAS,iBAAiB,CAAC;EAC1C,uBAAuB,KAAK;EAC5B,eAAe,KAAK;EACpB,6BAA6B,KAAK;EAClC,SAAS,KAAK;EACd,cAAc,KAAK;EACnB,UAAU,KAAK;EACf,MAAM,KAAK;EACX,oBAAoB,KAAK;EACzB,uBAAuB,KAAK;CAC9B;AACF;AAEA,SAAS,WAAW,OAAyC;CAC3D,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,IACrE,QACD,CAAC;AACP;;;;;;AAOA,SAAS,yBACP,QACA,YACA,UACA,QACM;CACN,MAAM,WAAW,OAAO,IAAI,UAAU,CAAC,EAAE;;;CAGzC,MAAM,eAAe,YAAY,SAAS,SAAS,aAAa,SAAS,OAAO;CAChF,sBAAsB,QAAQ,YAAY;EACxC,MAAM,gBAAgB,SAAS,QAAQ;EACvC,SAAS,uBAAuB,SAAS,WAAW;EACpD,UAAU,0BACR;GAAE,GAAG,WAAW,UAAU,QAAQ;GAAG,SAAS,SAAS;EAAQ,GAC/D,SAAS,aACT,YACA,MACF;CACF,CAAC;AACH;;;;;;;;;;;;;AAmBA,SAAS,gCACP,MACA,KACA,QACM;CACN,MAAM,WACJ,KAAK,iBAAiB,aACtB,KAAK,gBAAgB,aACrB,KAAK,gBAAgB,aACrB,QAAQ,IAAI,2BAA2B,KACvC,QAAQ,IAAI,0BAA0B,KACtC,QAAQ,IAAI,0BAA0B;CACxC,IAAI,UAAU;EACZ,OAAO,MAAM,0CAA0C,EACrD,QACE,mHACJ,CAAC;CACH;AACF;;;;;;;AAaA,eAAe,gBACb,UACA,YACA,QACA,gBACA,SACyE;CACzE,MAAM,UAAU,kBAAkB,eAAe,iBAAiB;CAClE,MAAM,SAAS,kBAAkB,eAAe,iBAAiB;CACjE,IAAI,eAAe,UAAU,SAAS;EACpC,QAAQ,OAAO,eAAe,SAAS,OAAO;CAChD;CAEA,MAAM,MAAe,WAAW,aAC5B,MAAM,YAAY,SAAS,SAAS,CAAC,CAAC,aAAa,CAAC,EAAE,IACtD,CAAC;CACL,IAAI,IAAI,KAAK;EACX,OAAO,OAAO,IAAI,GAAG;CACvB;CAEA,MAAM,WAAW,cAAc,YAAY;EACzC,SAAS,QAAQ;EACjB,UAAU,eAAe,UAAU,YAAY,aAAa;EAC5D,aAAa,SAAS;EACtB,WAAW,SAAS;EACpB,UAAU,SAAS;EACnB,QAAQ,OAAO;EACf;CACF,CAAC;CAED,MAAM,cAAc,UAAU,yBAAyB,OAAO,IAAI;CAClE,MAAM,YAAY,gBAChB,YACA,UACA,QACA,eAAe,WACf,WACF;CACA,MAAM,WAAW,IAAI,kBAAkB;EACrC;EACA,QAAQ;EACR;EACA,KAAK,eAAe;EACpB,eAAe;GACb,UAAU,UAAU,QAAQ,OAAO,KAAK;GACxC,SAAS,UAAU,OAAO,OAAO,KAAK;EACxC;CACF,CAAC;CAED,IAAI,eAAe,4BAA4B,OAAO;;EAEpD,qBAAqB,WAAW,QAAQ,CAAC,SAAS,MAAM,GAAG,EACzD,aAAa,mBACf,CAAC;CACH;CAEA,OAAO,KAAK,4BAA4B;EACtC,aAAa,WAAW;EACxB,WAAW,WAAW;EACtB,UAAU,WAAW;EACrB,0BAA0B,QAAQ,WAAW;CAC/C,CAAC;CAED,OAAO;EAAE,QAAQ;EAAY;EAAU;CAAQ;AACjD;AAEA,MAAM,aAAa,IAAI,0BAA0B;;;;;AAMjD,MAAM,mBAAmB;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;;;;;;;;;;;;;;AAmBA,OAAO,SAAS,wBACd,iBAAkD,CAAC,GACpC;CACf,OAAO,OAAO,OAAO;EACnB,IAAI;EACJ,QAAQ,OAAO,GAAG,WAAW,KAAK;;;GAGhC,MAAM,WACJ,gBAAgB,IAAI,QAAQ,QAAQ,KACpC,gBAAgB,QAAQ,IAAI,kBAAkB,KAC9C;;;GAIF,MAAM,cAAc,OAAO;GAC3B,MAAM,SACJ,eAAe,UAAU,mBAAmB,mBAAmB,QAAQ;GAEzE,IAAI;GACJ,IAAI;IACF,SAAS,wBAAwB,IAAI,OAAO;GAC9C,SAAS,OAAO;;;IAGd,OAAO,MAAM,8BAA8B,EAAE,OAAO,cAAc,KAAK,EAAE,CAAC;IAC1E;GACF;GAEA,MAAM,oBAAoB,kBAAkB,MAAM;GAClD,IAAI,qBAAqB,CAAC,OAAO,WAAW;;;IAG1C,OAAO,KAAK,+BAA+B;KACzC,SAAS,QAAQ,OAAO,OAAO;KAC/B,MAAM,QAAQ,OAAO,IAAI;IAC3B,CAAC;GACH;;;;;GAMA,MAAM,eACJ,eAAe,oBACb,MAAwB,KAAyB,YACjD,IAAI,mBAAmB,MAAM,KAAK,OAAO;GAC7C,MAAM,gBAAoD,oBACtD,aAAa,OAAO,MAAM,OAAO,WAAW;IAC1C;IACA,WAAW,eAAe;IAC1B,oBAAoB,eAAe;IACnC,UAAU,eAAe;IACzB,mBAAmB,eAAe;IAClC,UAAU,OAAO,SAAS,YAAY;GACxC,CAAC,IACD;GAEJ,MAAM,wBAAuC,UAAU,aAAa,IAAI,SAAS,OAAO,CAAC;;GAGzF,IAAI;GACJ,IAAI,gBAA+B,QAAQ,QAAQ;;GAEnD,IAAI,iBAAiB;;GAErB,IAAI,qBAAqB;GACzB,IAAI,aAAa;GACjB,IAAI;GACJ,MAAM,UAAU,IAAI,IAAoB;GAExC,MAAM,mBAAyB;IAC7B,QAAQ,KAAK;IACb,SAAS;IACT,iBAAiB;GACnB;GAEA,MAAM,sBAAsB,OAAO,aAAwD;;IAEzF,IAAI,oBAAoB;KACtB;IACF;IACA,MAAM,OAAO,IAAI,wBACf;KACE,SAAS,CAAC,0BAA0B,OAAO,MAAM,QAAQ,CAAC;KAC1D,gBAAgB;IAClB,GACA;KACE;KACA,WAAW,eAAe;KAC1B,oBAAoB,eAAe;KACnC,UAAU,eAAe,WAAW,aAAa,eAAe,QAAQ,IAAI;KAC5E,UAAU,eAAe,WAAW,aAAa,eAAe,QAAQ,IAAI;KAC5E,uBAAuB;KACvB,cAAc;IAChB,CACF;IACA,MAAM,KAAK,WAAW;IACtB,IAAI,oBAAoB;KACtB;IACF;IACA,MAAM,KAAK,MAAM,EAAE,QAAQ,KAAK,CAAC;IACjC,IAAI,oBAAoB;;KAEtB,KAAK,KAAK;KACV;IACF;IACA,SAAS;IACT,iBAAiB,MAAM,oBAAoB,OAAO,KAAK,IAAI,MAAM,MAAM;;IAEvE,MAAM,gBAAgB;GACxB;GAEA,IAAI,OAAO,UAAU;IACnB,MAAM,WAAW,OAAO;IACxB,MAAM,aAAa,OAAO,KAAK;IAE/B,eAAe,aAAa;KAC1B,MAAM,UAAU;MACd,IAAI;MACJ,GAAG;OACD,UAAU;OACV,MAAM;MACR,SAAS,YAAY;KACvB;KACA,cAAc;IAChB,CAAC;IAED,OAAO,IAAI,SAAS,WAAW,WAAW;KACxC,IAAI,kBAAkB,QAAQ,UAAU,GAAG;MACzC,qBAAqB;MACrB,iBAAiB;MACjB,WAAW;MACX,IAAI,CAAC,YAAY;OACf,aAAa;OACb,OAAO,MAAM,gDAAgD,EAAE,WAAW,CAAC;MAC7E;MACA;KACF;KACA,qBAAqB;KAErB,yBAAyB,QAAQ,YAAY,UAAU,MAAM;KAC7D,IAAI,aAAa;KACjB,IAAI,QAAQ;MACV,IAAI;OACF,MAAM,SAAS,OAAO,gBAAgB,UAAU;OAChD,aAAa,OAAO;OACpB,IAAI,OAAO,SAAS,GAAG;QACrB,sBAAsB,QAAQ,YAAY,MAAM;OAClD;MACF,QAAQ,CAER;KACF;KACA,sBAAsB,QAAQ,YAAY,gBAAgB,QAAQ,OAAO;KACzE,OAAO,MAAM,uCAAuC;MAAE;MAAY;KAAW,CAAC;KAE9E,IAAI,CAAC,gBAAgB;MACnB,iBAAiB;MACjB,gBAAgB,cACb,WAAW,oBAAoB,QAAQ,CAAC,CAAC,CACzC,OAAO,UAAU;;OAEhB,iBAAiB;OACjB,OAAO,MAAM,qCAAqC,EAAE,OAAO,aAAa,KAAK,EAAE,CAAC;MAClF,CAAC;KACL;IACF,CAAC;GACH;;;;GAKA,IAAI,OAAO,WAAW,eAAe;IACnC,MAAM,YAAY,IAAI,IAAI,OAAO,QAAQ,SAAS;IAClD,MAAM,UAAU;;;;;;;;IAQhB,OAAO,IAAI,QAAQ,KAAK,kBAAkB,UAAU;KAClD,MAAM,aAAa,MAAM,MAAM;KAC/B,IAAI,CAAC,UAAU,IAAI,UAAU,GAAG;MAC9B,OAAO,MAAM,6CAA6C,EAAE,WAAW,CAAC;MACxE,OAAO,OAAO;KAChB;KACA,OAAO,OAAO,WAAW;MACvB,KAAK,YAAY;OACf,MAAM,QAAQ,MAAM,QAAQ,gBAAgB,EAAE,aAAa,KAAK,CAAC;;;OAGjE,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,OAAO,GAAG;QAC5C,IAAI,IAAI,YAAY,MAAM,iBAAiB;SACzC,OAAO,MAAM,QAAQ;QACvB;OACF;OACA,MAAM,QAAQ,gBAAgB,GAAG,MAAM,aAAa,SAAS,GAAG,MAAM;OACtE,OAAO,MAAM,uCAAuC,EAAE,WAAW,CAAC;MACpE;MACA,QAAQ,UAAU;KACpB,CAAC,CAAC,CAAC,KACD,OAAO,UAAU,UACf,OAAO,WACL,OAAO,KAAK,iCAAiC;MAC3C;MACA,OAAO,aAAa,KAAK;KAC3B,CAAC,CACH,CACF,GACA,OAAO,KACT;IACF,CAAC;GACH;;GAGA,IAAI;GACJ,IAAI,OAAO,MAAM;IACf,MAAM,MAAM,eAAe,OAAO,QAAQ;IAC1C,MAAM,aAAa,kBAAkB,OAAO,MAAM,GAAG;IACrD,IAAI,WAAW,QAAQ;KACrB,gCAAgC,OAAO,MAAM,KAAK,MAAM;KACxD,MAAM,QAAQ,OAAO,OAAO,cAC1B,gBACE;MAAE,WAAW,IAAI,SAAS;MAAW,WAAW,IAAI,SAAS,SAAS;KAAG,GACzE,YACA,QACA,gBACA,aACF,CACF;KACA,OAAO;KACP,MAAM,EAAE,aAAa;KACrB,MAAM,UAAU,IAAI,iBAAiB,UAAU,eAAe,GAAG;KAEjE,OAAO,OAAO,WACZ,OAAO,WAAW,IAAI,MAAM,UAAU,EAAE,OAAO,iBAAiB,CAAC,IAAI,UACnE,OAAO,WAAW,QAAQ,OAAO,KAA6B,CAAC,CACjE,CAAC,CAAC,KACA,OAAO,UAAU,UACf,OAAO,WACL,OAAO,KAAK,wCAAwC,EAClD,OAAO,aAAa,KAAK,EAC3B,CAAC,CACH,CACF,GACA,OAAO,MACT,CACF;KAEA,OAAO,IAAI,QAAQ,KAAK,WAAW,UACjC,OAAO,WAAW;MAChB,MAAM,CAAC,OAAO,UAAU,YAAY,KAAK;MACzC,SAAS,cAAc,OAAO,MAAM;KACtC,CAAC,CACH;KACA,OAAO,IAAI,QAAQ,KAAK,YAAY,UAClC,OAAO,WAAW;MAChB,MAAM,CAAC,OAAO,UAAU,aAAa,KAAK;MAC1C,SAAS,aAAa,OAAO,MAAM;KACrC,CAAC,CACH;KACA,OAAO,IAAI,KAAK,KAAK,mBAAmB,UACtC,OAAO,WAAW,SAAS,aAAa,gBAAgB,KAAK,CAAC,CAAC,CACjE;KACA,OAAO,IAAI,KAAK,KAAK,kBAAkB,UACrC,OAAO,WAAW;MAChB,MAAM,CAAC,OAAO,UAAU,eAAe;OACrC,MAAM,MAAM;OACZ,WAAW,MAAM;OACjB,IAAI,MAAM;OACV,QAAQ,MAAM;OACd,QAAQ,MAAM,WAAW,cAAc,MAAM,SAAS;MACxD,CAAC;MACD,SAAS,YAAY,OAAO,MAAM;KACpC,CAAC,CACH;KACA,OAAO,IAAI,WAAW,KAAK,aAAa,UACtC,OAAO,WAAW;MAChB,MAAM,CAAC,OAAO,UAAU,gBAAgB,KAAK;MAC7C,SAAS,gBAAgB,OAAO,MAAM;KACxC,CAAC,CACH;KAEA,IAAI,WAAW,uBAAuB;;;MAGpC,OAAO,IAAI,QAAQ,KAAK,iBAAiB,UACvC,OAAO,WAAW;OAChB,MAAM,UAAU,SAAS,mBAAmB;OAC5C,IAAI,CAAC,SAAS;QACZ;OACF;OACA,MAAM,UAAkC,CAAC;OACzC,WAAW,OAAO,SAAS,SAAS,oBAAoB;OACxD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,GAAG;;QAElD,IAAI,CAAC,MAAM,QAAQ,QAAQ,IAAI,GAAG,GAAG;SACnC,MAAM,QAAQ,QAAQ,IAAI,KAAK,KAAK;QACtC;OACF;MACF,CAAC,CACH;MACA,OAAO,MAAM,4CAA4C,CAAC,CAAC;KAC7D;IACF,OAAO;KACL,OAAO,KAAK,6BAA6B;MACvC,SAAS,WAAW;MACpB,QAAQ,WAAW,UAAU,2BAA2B;KAC1D,CAAC;IACH;GACF;GAEA,OAAO,OAAO,mBACZ,OAAO,WAAW;IAChB,WAAW;;IAEX,MAAM,SAAS,QAAQ,EAAE,MAAM,2BAA2B,CAAC;GAC7D,CAAC,CACH;GAEA,OAAO,KAAK,4BAA4B;IACtC,SAAS,QAAQ,OAAO,WAAW,aAAa;IAChD,UAAU,OAAO,SAAS,YAAY;IACtC,MAAM,QAAQ,IAAI;IAClB,UAAU,QAAQ,OAAO,QAAQ;IACjC,WAAW,OAAO,cAAc,oBAAoB,cAAc;GACpE,CAAC;EACH,CAAC;CACH,CAAC;AACH;AAEA,OAAO,MAAM,oBAAmC,wBAAwB;AAExE,eAAe","names":[],"sources":["../src/opencode.ts"],"version":3,"file":"opencode.js","sourceRoot":""}
1
+ {"mappings":"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","names":[],"sources":["../src/opencode.ts"],"version":3,"file":"opencode.js","sourceRoot":""}
package/dist/plugin.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type AuthServerConfig, type Logger, type TokenSet } from "@vymalo/opencode-auth-core/lib";
1
+ import { type AuthServerConfig, type DeviceSignIn, type Logger, type TokenSet } from "@vymalo/opencode-auth-core/lib";
2
2
  /**
3
3
  * Identity for the exchanged project-token store. Kept as a constant, not
4
4
  * `auth.id`, because the exchanged-token key has always been derived from this
@@ -54,10 +54,28 @@ export interface LightbridgeRuntimeOptions {
54
54
  * `TokenRuntime` (no network, no disk).
55
55
  */
56
56
  export interface LightbridgeRuntimeLike {
57
- getProjectToken(options?: {
58
- interactive?: boolean;
57
+ /**
58
+ * A usable gateway/OTEL bearer. NEVER interactive (ADR-0023): when no usable
59
+ * token exists it rejects with `InteractiveAuthRequiredError` and the caller
60
+ * fails closed. The only way a human signs in is `beginDeviceSignIn`, driven
61
+ * from the host's Connect dialog.
62
+ */
63
+ getProjectToken(): Promise<TokenSet>;
64
+ /**
65
+ * The shared human/IdP root token, refresh-only (never interactive).
66
+ * `minValidityMs` forces a real refresh when the cached token has less than
67
+ * that left (the host's 5-minute refresh window is wider than our skew).
68
+ */
69
+ ensureRootToken(options?: {
70
+ minValidityMs?: number;
59
71
  }): Promise<TokenSet>;
60
- reset?(): Promise<void>;
72
+ /**
73
+ * Request a device code for the Connect dialog; `complete` polls and stores.
74
+ * `signal` cancels the device-authorization request.
75
+ */
76
+ beginDeviceSignIn(signal?: AbortSignal): Promise<DeviceSignIn>;
77
+ /** Drop every stored token for this identity (the host disconnected it). */
78
+ reset(): Promise<void>;
61
79
  }
62
80
  /**
63
81
  * Builds a `LightbridgeRuntimeLike` for a given `(auth, projectId)` pair.
@@ -117,10 +135,18 @@ export declare class LightbridgeRuntime implements LightbridgeRuntimeLike {
117
135
  * invents a token: a failure propagates to the caller, which is expected to
118
136
  * fail closed (no header / empty `headers()`).
119
137
  */
120
- getProjectToken(options?: {
121
- interactive?: boolean;
122
- }): Promise<TokenSet>;
138
+ getProjectToken(): Promise<TokenSet>;
123
139
  private performExchange;
140
+ /** See {@link LightbridgeRuntimeLike.ensureRootToken}. */
141
+ ensureRootToken(options?: {
142
+ minValidityMs?: number;
143
+ }): Promise<TokenSet>;
144
+ /**
145
+ * The ONLY interactive entry point (ADR-0023): the root runtime requests a
146
+ * device code and, on `complete`, stores the result through the shared
147
+ * credential file's single writer (`setCached` under the refresh lock).
148
+ */
149
+ beginDeviceSignIn(signal?: AbortSignal): Promise<DeviceSignIn>;
124
150
  /**
125
151
  * Drop the cached tokens for this identity: the exchanged project token
126
152
  * entirely (its own exclusive store), and the shared root credential. The
package/dist/plugin.js CHANGED
@@ -168,9 +168,9 @@ export class LightbridgeRuntime {
168
168
  * invents a token: a failure propagates to the caller, which is expected to
169
169
  * fail closed (no header / empty `headers()`).
170
170
  */
171
- async getProjectToken(options = {}) {
171
+ async getProjectToken() {
172
172
  if (!this.exchange) {
173
- return this.rootRuntime.ensure({ interactive: options.interactive });
173
+ return this.rootRuntime.ensure({ interactive: false });
174
174
  }
175
175
  const cached = await this.getCachedProjectToken();
176
176
  if (isProjectTokenUsable(cached, this.tokenExpirySkewMs)) {
@@ -181,7 +181,7 @@ export class LightbridgeRuntime {
181
181
  if (this.inFlightExchange) {
182
182
  return this.inFlightExchange;
183
183
  }
184
- const exchange = this.performExchange(options);
184
+ const exchange = this.performExchange();
185
185
  this.inFlightExchange = exchange;
186
186
  try {
187
187
  return await exchange;
@@ -191,8 +191,8 @@ export class LightbridgeRuntime {
191
191
  }
192
192
  }
193
193
  }
194
- async performExchange(options) {
195
- const human = await this.rootRuntime.ensure({ interactive: options.interactive });
194
+ async performExchange() {
195
+ const human = await this.rootRuntime.ensure({ interactive: false });
196
196
  this.logger.info("lightbridge_exchange_started", { projectId: this.projectId ?? "(default)" });
197
197
  try {
198
198
  // No `projectId` → send no `project_id` param; the backend mints a token
@@ -208,6 +208,21 @@ export class LightbridgeRuntime {
208
208
  throw error;
209
209
  }
210
210
  }
211
+ /** See {@link LightbridgeRuntimeLike.ensureRootToken}. */
212
+ async ensureRootToken(options = {}) {
213
+ return this.rootRuntime.ensure({
214
+ interactive: false,
215
+ minValidityMs: options.minValidityMs
216
+ });
217
+ }
218
+ /**
219
+ * The ONLY interactive entry point (ADR-0023): the root runtime requests a
220
+ * device code and, on `complete`, stores the result through the shared
221
+ * credential file's single writer (`setCached` under the refresh lock).
222
+ */
223
+ async beginDeviceSignIn(signal) {
224
+ return this.rootRuntime.beginDeviceSignIn(signal);
225
+ }
211
226
  /**
212
227
  * Drop the cached tokens for this identity: the exchanged project token
213
228
  * entirely (its own exclusive store), and the shared root credential. The
@@ -1 +1 @@
1
- {"mappings":"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","names":[],"sources":["../src/plugin.ts"],"version":3,"file":"plugin.js","sourceRoot":""}
1
+ {"mappings":"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","names":[],"sources":["../src/plugin.ts"],"version":3,"file":"plugin.js","sourceRoot":""}
@@ -0,0 +1,70 @@
1
+ import type { Credential, Plugin } from "@opencode/plugin/effect";
2
+ import { type TokenSet } from "@vymalo/opencode-auth-core/lib";
3
+ import type { Logger } from "./logging.js";
4
+ import type { LightbridgeRuntimeLike } from "./plugin.js";
5
+ type IntegrationEditor = Parameters<Parameters<Plugin.Context["integration"]["transform"]>[0]>[0];
6
+ /** The host's oauth-method registration shape (the package does not export it by name). */
7
+ export type IntegrationOAuthMethodRegistration = Extract<Parameters<IntegrationEditor["method"]["update"]>[0], {
8
+ method: {
9
+ type: "oauth";
10
+ };
11
+ }>;
12
+ /** Id of the one sign-in method lightbridge registers on its integration (ADR-0023). */
13
+ export declare const SIGN_IN_METHOD_ID = "device";
14
+ /** Label of the button the host renders for that method. */
15
+ export declare const SIGN_IN_METHOD_LABEL = "Sign in";
16
+ /** The host calls a method's `refresh` once the credential is within this of `expires`. */
17
+ export declare const HOST_REFRESH_WINDOW_MS: number;
18
+ /** The exact path a user follows to sign in, for the `lightbridge_sign_in_required` hint. */
19
+ export declare function signInPath(name: string): string;
20
+ /**
21
+ * Display-only account label (email / username) read from the access token's
22
+ * claims. Deliberately UNVERIFIED: nothing security-relevant ever reads it, it
23
+ * only decorates the host's connection row. Opaque (non-JWT) tokens and any
24
+ * decoding problem yield `undefined`.
25
+ */
26
+ export declare function accountLabel(accessToken: string): string | undefined;
27
+ /**
28
+ * The host-side projection of our token: a "connected" marker plus the current
29
+ * access token. CUSTODY RULE (ADR-0023): `refresh` is ALWAYS `""` — the refresh
30
+ * token never leaves lightbridge's own state file, so a host credential-store
31
+ * leak or a host-driven refresh cannot replay (and thereby rotate away) it.
32
+ */
33
+ export declare function projectCredential(token: TokenSet, now?: number): Credential.OAuth;
34
+ export interface SignInDependencies {
35
+ integrationID: string;
36
+ runtime: LightbridgeRuntimeLike;
37
+ logger: Logger;
38
+ /**
39
+ * Runs after the projection was handed back (kick the model sync, reload the
40
+ * host's providers). Detached: the dialog closes without waiting for it, and
41
+ * a failure or a late interrupt cannot undo the sign-in.
42
+ */
43
+ afterSignIn: () => Promise<void>;
44
+ /** Called synchronously on a successful sign-in (re-arms the sign-in notice). */
45
+ onSignedIn?: () => void;
46
+ /** Called when a sign-in-related call finds no usable token (refresh-only failure). */
47
+ onSignInRequired?: (source: string) => void;
48
+ }
49
+ /**
50
+ * The oauth method registration behind the host's "Connect" dialog (ADR-0023).
51
+ * `authorize` requests a device code and hands the host the URL + code to show;
52
+ * `callback` awaits the user's approval (interruptible: the host closing the
53
+ * dialog interrupts it, which aborts the polling) and returns the projection.
54
+ */
55
+ export declare function createSignInRegistration(deps: SignInDependencies): IntegrationOAuthMethodRegistration;
56
+ export interface SignInNotice {
57
+ /** Warn (once until re-armed) that sign-in is needed; always records the source at debug. */
58
+ notify(source: string): void;
59
+ /** Re-arm: the next `notify` warns again (after a sign-in, or a host disconnect). */
60
+ reset(): void;
61
+ }
62
+ /**
63
+ * Emit `lightbridge_sign_in_required` at most once per arming, naming the exact
64
+ * path to sign in. Every non-interactive caller that finds no usable token
65
+ * (startup check, gateway header, OTEL token source, the register sync) reports
66
+ * through this one latch; each call is also recorded at `debug` as
67
+ * `lightbridge_sign_in_required_seen` so the sources stay observable.
68
+ */
69
+ export declare function createSignInRequiredNotifier(logger: Logger, name: string): SignInNotice;
70
+ export {};
@@ -0,0 +1,152 @@
1
+ import { isInteractiveAuthRequiredError } from "@vymalo/opencode-auth-core/lib";
2
+ import { Effect } from "effect";
3
+ /** Id of the one sign-in method lightbridge registers on its integration (ADR-0023). */
4
+ export const SIGN_IN_METHOD_ID = "device";
5
+ /** Label of the button the host renders for that method. */
6
+ export const SIGN_IN_METHOD_LABEL = "Sign in";
7
+ /** Fallback lifetime for a token the IdP gave no `expires_in` for. */
8
+ const FALLBACK_LIFETIME_MS = 60 * 60 * 1e3;
9
+ const MAX_LABEL_CHARS = 80;
10
+ /** The host calls a method's `refresh` once the credential is within this of `expires`. */
11
+ export const HOST_REFRESH_WINDOW_MS = 5 * 60 * 1e3;
12
+ /** The exact path a user follows to sign in, for the `lightbridge_sign_in_required` hint. */
13
+ export function signInPath(name) {
14
+ return `Settings → Providers → Show more providers → (Integrations dialog) search "${name}" → Sign in`;
15
+ }
16
+ /**
17
+ * Display-only account label (email / username) read from the access token's
18
+ * claims. Deliberately UNVERIFIED: nothing security-relevant ever reads it, it
19
+ * only decorates the host's connection row. Opaque (non-JWT) tokens and any
20
+ * decoding problem yield `undefined`.
21
+ */
22
+ export function accountLabel(accessToken) {
23
+ const parts = accessToken.split(".");
24
+ if (parts.length !== 3 || !parts[1]) {
25
+ return undefined;
26
+ }
27
+ try {
28
+ const claims = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
29
+ for (const key of ["email", "preferred_username"]) {
30
+ const value = claims[key];
31
+ if (typeof value === "string" && value.trim().length > 0) {
32
+ return value.trim().slice(0, MAX_LABEL_CHARS);
33
+ }
34
+ }
35
+ } catch {}
36
+ return undefined;
37
+ }
38
+ /**
39
+ * The host-side projection of our token: a "connected" marker plus the current
40
+ * access token. CUSTODY RULE (ADR-0023): `refresh` is ALWAYS `""` — the refresh
41
+ * token never leaves lightbridge's own state file, so a host credential-store
42
+ * leak or a host-driven refresh cannot replay (and thereby rotate away) it.
43
+ */
44
+ export function projectCredential(token, now = Date.now()) {
45
+ const label = accountLabel(token.accessToken);
46
+ return {
47
+ type: "oauth",
48
+ methodID: SIGN_IN_METHOD_ID,
49
+ access: token.accessToken,
50
+ refresh: "",
51
+ expires: Math.floor(token.expiresAt ?? now + FALLBACK_LIFETIME_MS),
52
+ ...label ? { metadata: { label } } : {}
53
+ };
54
+ }
55
+ /**
56
+ * The oauth method registration behind the host's "Connect" dialog (ADR-0023).
57
+ * `authorize` requests a device code and hands the host the URL + code to show;
58
+ * `callback` awaits the user's approval (interruptible: the host closing the
59
+ * dialog interrupts it, which aborts the polling) and returns the projection.
60
+ */
61
+ export function createSignInRegistration(deps) {
62
+ const { integrationID, runtime, logger } = deps;
63
+ return {
64
+ integrationID,
65
+ method: {
66
+ id: SIGN_IN_METHOD_ID,
67
+ type: "oauth",
68
+ label: SIGN_IN_METHOD_LABEL
69
+ },
70
+ authorize: () => Effect.tryPromise({
71
+ // The effect's signal aborts when the host abandons the attempt, which
72
+ // also cancels the device-authorization request.
73
+ try: (signal) => runtime.beginDeviceSignIn(signal),
74
+ catch: (error) => error
75
+ }).pipe(Effect.tapError((error) => Effect.sync(() => logger.error("lightbridge_sign_in_begin_failed", errorFields(error)))), Effect.map((session) => ({
76
+ url: session.verificationUriComplete ?? session.verificationUri,
77
+ instructions: `Confirm the code ${session.userCode} on the page that opens, then approve the request.`,
78
+ expiresAt: session.expiresAt,
79
+ mode: "auto",
80
+ callback: Effect.tryPromise({
81
+ try: (signal) => session.complete(signal),
82
+ catch: (error) => error
83
+ }).pipe(Effect.tapError((error) => Effect.sync(() => logger.warn("lightbridge_sign_in_failed", errorFields(error)))), Effect.onInterrupt(() => Effect.sync(() => logger.info("lightbridge_sign_in_cancelled", { integrationID }))), Effect.map((token) => {
84
+ logger.info("lightbridge_sign_in_completed", { integrationID });
85
+ deps.onSignedIn?.();
86
+ // Detached on purpose (see `afterSignIn`).
87
+ void (async () => {
88
+ try {
89
+ await deps.afterSignIn();
90
+ } catch (error) {
91
+ logger.warn("lightbridge_sign_in_followup_failed", errorFields(error));
92
+ }
93
+ })();
94
+ return projectCredential(token);
95
+ }))
96
+ }))),
97
+ // The host calls this within HOST_REFRESH_WINDOW_MS of `expires`. Whatever it
98
+ // holds is ignored (it has no refresh token): the truth is our own runtime,
99
+ // forced to a real, non-interactive refresh through the single writer. A
100
+ // revoked/cleared root fails here - it never starts a flow.
101
+ refresh: () => Effect.tryPromise({
102
+ try: () => runtime.ensureRootToken({ minValidityMs: HOST_REFRESH_WINDOW_MS }),
103
+ catch: (error) => error
104
+ }).pipe(Effect.tapError((error) => Effect.sync(() => {
105
+ logger.warn("lightbridge_sign_in_refresh_failed", errorFields(error));
106
+ if (isInteractiveAuthRequiredError(error)) {
107
+ deps.onSignInRequired?.("refresh");
108
+ }
109
+ })), Effect.tap((token) => Effect.sync(() => {
110
+ // A refresh that "succeeds" with a token still inside the window means
111
+ // the refresh itself failed and we served what was left.
112
+ if (token.expiresAt !== undefined && token.expiresAt - Date.now() <= HOST_REFRESH_WINDOW_MS) {
113
+ logger.warn("lightbridge_sign_in_refresh_failed", { error: "refresh returned a token still inside the host refresh window" });
114
+ }
115
+ })), Effect.map((token) => projectCredential(token))),
116
+ label: (credential) => {
117
+ const label = credential.metadata?.label;
118
+ return typeof label === "string" ? label : undefined;
119
+ }
120
+ };
121
+ }
122
+ function errorFields(error) {
123
+ return { error: error instanceof Error ? error.message : String(error) };
124
+ }
125
+ /**
126
+ * Emit `lightbridge_sign_in_required` at most once per arming, naming the exact
127
+ * path to sign in. Every non-interactive caller that finds no usable token
128
+ * (startup check, gateway header, OTEL token source, the register sync) reports
129
+ * through this one latch; each call is also recorded at `debug` as
130
+ * `lightbridge_sign_in_required_seen` so the sources stay observable.
131
+ */
132
+ export function createSignInRequiredNotifier(logger, name) {
133
+ let notified = false;
134
+ return {
135
+ notify(source) {
136
+ logger.debug("lightbridge_sign_in_required_seen", { source });
137
+ if (notified) {
138
+ return;
139
+ }
140
+ notified = true;
141
+ logger.warn("lightbridge_sign_in_required", {
142
+ source,
143
+ message: `lightbridge is not signed in: open ${signInPath(name)}`
144
+ });
145
+ },
146
+ reset() {
147
+ notified = false;
148
+ }
149
+ };
150
+ }
151
+
152
+ //# sourceMappingURL=sign-in.js.map
@@ -0,0 +1 @@
1
+ {"mappings":"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","names":[],"sources":["../src/sign-in.ts"],"version":3,"file":"sign-in.js","sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vymalo/opencode-lightbridge",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "Umbrella OpenCode plugin for ADR-0012: one shared credential (TokenRuntime) drives both the LLM gateway bearer and OTEL export, so a developer authenticates once and every egress rides the same project-scoped token.",
5
5
  "license": "MIT",
6
6
  "author": "vymalo contributors",
@@ -54,9 +54,9 @@
54
54
  "@opentelemetry/api": "^1.9.1",
55
55
  "@opentelemetry/api-logs": "^0.222.0",
56
56
  "@opentelemetry/core": "^2.11.0",
57
- "@vymalo/opencode-auth-core": "0.19.0",
58
- "@vymalo/opencode-core-otel": "0.19.0",
59
- "@vymalo/opencode-provider-sync": "0.19.0"
57
+ "@vymalo/opencode-auth-core": "0.20.0",
58
+ "@vymalo/opencode-provider-sync": "0.20.0",
59
+ "@vymalo/opencode-core-otel": "0.20.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@opentelemetry/sdk-logs": "^0.222.0",