@continuous-excellence/ze-great-dashboard-aws 0.17.0 → 0.18.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/lambda.mjs CHANGED
@@ -50688,8 +50688,8 @@ function uint8ArrayToBase64(bytes) {
50688
50688
  }
50689
50689
  return btoa(binaryString);
50690
50690
  }
50691
- function base64urlToUint8Array(base64url3) {
50692
- const base643 = base64url3.replace(/-/g, "+").replace(/_/g, "/");
50691
+ function base64urlToUint8Array(base64url4) {
50692
+ const base643 = base64url4.replace(/-/g, "+").replace(/_/g, "/");
50693
50693
  const padding = "=".repeat((4 - base643.length % 4) % 4);
50694
50694
  return base64ToUint8Array(base643 + padding);
50695
50695
  }
@@ -64019,11 +64019,38 @@ var panelSchema = external_exports.looseObject({
64019
64019
  });
64020
64020
  }
64021
64021
  });
64022
- var sourceSchema = external_exports.looseObject({
64023
- type: external_exports.string().min(1),
64024
- /** Credentials are never in the config — only the name of the env var holding one. */
64025
- token_env: external_exports.string().min(1).optional()
64022
+ var githubAppSchema = external_exports.object({
64023
+ app_id_env: external_exports.string().min(1),
64024
+ private_key_env: external_exports.string().min(1),
64025
+ installation_id_env: external_exports.string().min(1)
64026
64026
  });
64027
+ var sourceAuthenticationSchema = {
64028
+ /** Credentials are never in the config — only the name of the env var holding one. */
64029
+ token_env: external_exports.string().min(1).optional(),
64030
+ github_app: githubAppSchema.optional()
64031
+ };
64032
+ function exactlyOneGithubAuthenticationMode(source, ctx) {
64033
+ if (source.token_env && source.github_app)
64034
+ ctx.addIssue({ code: "custom", message: "configure token_env or github_app, not both" });
64035
+ }
64036
+ var githubActionsSourceSchema = external_exports.looseObject({
64037
+ type: external_exports.literal("github-actions"),
64038
+ repo: external_exports.string().regex(/^[^/\s]+\/[^/\s]+$/, "must be an owner/repository pair"),
64039
+ /** The branch whose workflow health the dashboard represents. */
64040
+ branch: external_exports.string().min(1).optional(),
64041
+ ...sourceAuthenticationSchema
64042
+ }).superRefine(exactlyOneGithubAuthenticationMode);
64043
+ var sourceSchema = external_exports.looseObject({ type: external_exports.string().min(1), ...sourceAuthenticationSchema }).superRefine(exactlyOneGithubAuthenticationMode);
64044
+ function credentialEnvironmentNames(source) {
64045
+ return [
64046
+ ...source.token_env ? [source.token_env] : [],
64047
+ ...source.github_app ? [
64048
+ source.github_app.app_id_env,
64049
+ source.github_app.private_key_env,
64050
+ source.github_app.installation_id_env
64051
+ ] : []
64052
+ ];
64053
+ }
64027
64054
  var boardSchema = external_exports.object({
64028
64055
  refresh: durationSchema.optional(),
64029
64056
  running_refresh: durationSchema.optional(),
@@ -66421,14 +66448,119 @@ function formatNames(names) {
66421
66448
  return names.length ? names.join(", ") : "(none)";
66422
66449
  }
66423
66450
 
66451
+ // packages/server/src/github-auth.ts
66452
+ import { createSign } from "node:crypto";
66453
+ var GithubAuthenticationError = class extends Error {
66454
+ constructor() {
66455
+ super("GitHub authentication could not be completed.");
66456
+ this.name = "GithubAuthenticationError";
66457
+ }
66458
+ };
66459
+ function createGithubClient(credentials, now = Date.now) {
66460
+ const tokens = /* @__PURE__ */ new Map();
66461
+ const pending2 = /* @__PURE__ */ new Map();
66462
+ async function installationToken(source, fetcher, refresh = false) {
66463
+ const app = source.github_app;
66464
+ if (!app) return void 0;
66465
+ const appId = requiredCredential(credentials, app.app_id_env);
66466
+ const privateKey = requiredCredential(credentials, app.private_key_env);
66467
+ const installationId = requiredCredential(credentials, app.installation_id_env);
66468
+ const cacheKey = `${appId}:${installationId}:${app.private_key_env}`;
66469
+ const cached2 = tokens.get(cacheKey);
66470
+ if (!refresh && cached2 && cached2.expiresAt > now() + 6e4)
66471
+ return { token: cached2.token, cacheKey };
66472
+ const existing = pending2.get(cacheKey);
66473
+ if (existing) return { token: await existing, cacheKey };
66474
+ const exchange = exchangeInstallationToken({ appId, privateKey, installationId, fetcher, now }).then(({ token, expiresAt }) => {
66475
+ tokens.set(cacheKey, { token, expiresAt });
66476
+ return token;
66477
+ }).catch((error52) => {
66478
+ if (error52 instanceof GithubAuthenticationError) throw error52;
66479
+ throw new GithubAuthenticationError();
66480
+ });
66481
+ pending2.set(cacheKey, exchange);
66482
+ try {
66483
+ return { token: await exchange, cacheKey };
66484
+ } finally {
66485
+ pending2.delete(cacheKey);
66486
+ }
66487
+ }
66488
+ return {
66489
+ async get({ source, url: url2, requestHeaders, fetcher }) {
66490
+ const headers = githubHeaders(requestHeaders);
66491
+ if (source.token_env)
66492
+ headers.set("authorization", `Bearer ${requiredCredential(credentials, source.token_env)}`);
66493
+ const appToken = await installationToken(source, fetcher);
66494
+ if (appToken) headers.set("authorization", `Bearer ${appToken.token}`);
66495
+ const response = await fetcher(url2, { headers });
66496
+ if (!appToken || response.status !== 401) return response;
66497
+ tokens.delete(appToken.cacheKey);
66498
+ const refreshed = await installationToken(source, fetcher, true);
66499
+ if (!refreshed) return response;
66500
+ const replayHeaders = githubHeaders(requestHeaders);
66501
+ replayHeaders.set("authorization", `Bearer ${refreshed.token}`);
66502
+ return fetcher(url2, { headers: replayHeaders });
66503
+ }
66504
+ };
66505
+ }
66506
+ function githubHeaders(requestHeaders) {
66507
+ const headers = new Headers({ accept: "application/vnd.github+json" });
66508
+ for (const name of ["if-none-match", "if-modified-since"]) {
66509
+ const value = requestHeaders.get(name);
66510
+ if (value) headers.set(name, value);
66511
+ }
66512
+ return headers;
66513
+ }
66514
+ async function exchangeInstallationToken(args) {
66515
+ let jwt2;
66516
+ try {
66517
+ jwt2 = createAppJwt(args.appId, args.privateKey, args.now());
66518
+ } catch {
66519
+ throw new GithubAuthenticationError();
66520
+ }
66521
+ let response;
66522
+ try {
66523
+ response = await args.fetcher(
66524
+ `https://api.github.com/app/installations/${encodeURIComponent(args.installationId)}/access_tokens`,
66525
+ {
66526
+ method: "POST",
66527
+ headers: new Headers({
66528
+ accept: "application/vnd.github+json",
66529
+ authorization: `Bearer ${jwt2}`,
66530
+ "content-type": "application/json"
66531
+ })
66532
+ }
66533
+ );
66534
+ } catch {
66535
+ throw new GithubAuthenticationError();
66536
+ }
66537
+ if (!response.ok) throw new GithubAuthenticationError();
66538
+ const body = await response.json();
66539
+ if (!body.token || !body.expires_at) throw new GithubAuthenticationError();
66540
+ const expiresAt = new Date(body.expires_at).valueOf();
66541
+ if (!Number.isFinite(expiresAt)) throw new GithubAuthenticationError();
66542
+ return { token: body.token, expiresAt };
66543
+ }
66544
+ function createAppJwt(appId, privateKey, now = Date.now()) {
66545
+ const issuedAt = Math.floor(now / 1e3) - 60;
66546
+ const header = base64url3(JSON.stringify({ alg: "RS256", typ: "JWT" }));
66547
+ const payload2 = base64url3(JSON.stringify({ iat: issuedAt, exp: issuedAt + 540, iss: appId }));
66548
+ const signingInput = `${header}.${payload2}`;
66549
+ const signer = createSign("RSA-SHA256");
66550
+ signer.update(signingInput);
66551
+ signer.end();
66552
+ return `${signingInput}.${base64url3(signer.sign(privateKey))}`;
66553
+ }
66554
+ function requiredCredential(credentials, name) {
66555
+ const value = credentials.get(name);
66556
+ if (value) return value;
66557
+ throw new GithubAuthenticationError();
66558
+ }
66559
+ function base64url3(value) {
66560
+ return Buffer.from(value).toString("base64url");
66561
+ }
66562
+
66424
66563
  // packages/server/src/adapters/github-actions.ts
66425
- var githubSourceSchema = external_exports.object({
66426
- type: external_exports.literal("github-actions"),
66427
- repo: external_exports.string().regex(/^[^/\s]+\/[^/\s]+$/, "must be an owner/repository pair"),
66428
- /** The branch whose workflow health the dashboard represents. */
66429
- branch: external_exports.string().min(1).optional(),
66430
- token_env: external_exports.string().min(1).optional()
66431
- });
66432
66564
  var pipelinePanelSchema = external_exports.object({
66433
66565
  id: external_exports.string().min(1),
66434
66566
  type: external_exports.literal("pipeline-status"),
@@ -66479,34 +66611,30 @@ var pullRequestsSchema = external_exports.array(
66479
66611
  base: external_exports.object({ ref: external_exports.string().min(1) })
66480
66612
  })
66481
66613
  );
66482
- function permittedGithubActionsCalls(panel, source, credentials = environmentCredentials()) {
66614
+ function permittedGithubActionsCalls(panel, source, _credentials) {
66483
66615
  const parsedPanel = pipelinePanelSchema.parse(panel);
66484
- const parsedSource = githubSourceSchema.parse(source);
66616
+ const parsedSource = githubActionsSourceSchema.parse(source);
66485
66617
  const url2 = new URL(
66486
66618
  `https://api.github.com/repos/${parsedSource.repo}/actions/workflows/${encodeURIComponent(parsedPanel.pipeline)}/runs`
66487
66619
  );
66488
66620
  if (parsedSource.branch) url2.searchParams.set("branch", parsedSource.branch);
66489
66621
  url2.searchParams.set("per_page", "1");
66490
- const headers = new Headers({ accept: "application/vnd.github+json" });
66491
- const token = parsedSource.token_env ? credentials.get(parsedSource.token_env) : void 0;
66492
- if (token) headers.set("authorization", `Bearer ${token}`);
66493
- return [{ url: url2.toString(), headers }];
66622
+ return [{ url: url2.toString(), headers: new Headers() }];
66494
66623
  }
66495
- function permittedGithubActionsPullRequestHealthCalls(panel, source, credentials = environmentCredentials()) {
66624
+ function permittedGithubActionsPullRequestHealthCalls(panel, source) {
66496
66625
  const parsedPanel = pullRequestHealthPanelSchema.parse(panel);
66497
- const parsedSource = githubSourceSchema.parse(source);
66626
+ const parsedSource = githubActionsSourceSchema.parse(source);
66498
66627
  const calls = parsedPanel.update_workflows.map(
66499
- ({ workflow }) => githubRunsCall(parsedSource, workflow, void 0, void 0, credentials)
66628
+ ({ workflow }) => githubRunsCall(parsedSource, workflow)
66500
66629
  );
66501
66630
  calls.push({
66502
- url: pullRequestsCall(parsedSource, parsedPanel.base_branch, 1, credentials).url,
66503
- headers: githubHeaders(parsedSource, credentials)
66631
+ ...pullRequestsCall(parsedSource, parsedPanel.base_branch, 1)
66504
66632
  });
66505
66633
  return calls;
66506
66634
  }
66507
66635
  async function fetchGithubActionsPullRequestHealth(args) {
66508
66636
  const panel = pullRequestHealthPanelSchema.parse(args.panel);
66509
- const source = githubSourceSchema.parse(args.source);
66637
+ const source = githubActionsSourceSchema.parse(args.source);
66510
66638
  try {
66511
66639
  const workflowResults = await Promise.all(
66512
66640
  panel.update_workflows.map(async ({ workflow }) => ({
@@ -66516,7 +66644,7 @@ async function fetchGithubActionsPullRequestHealth(args) {
66516
66644
  workflow,
66517
66645
  requestHeaders: args.requestHeaders,
66518
66646
  fetcher: args.fetcher,
66519
- credentials: args.credentials ?? environmentCredentials()
66647
+ githubClient: githubClientFor(args)
66520
66648
  })
66521
66649
  }))
66522
66650
  );
@@ -66525,7 +66653,7 @@ async function fetchGithubActionsPullRequestHealth(args) {
66525
66653
  baseBranch: panel.base_branch,
66526
66654
  requestHeaders: args.requestHeaders,
66527
66655
  fetcher: args.fetcher,
66528
- credentials: args.credentials ?? environmentCredentials()
66656
+ githubClient: githubClientFor(args)
66529
66657
  });
66530
66658
  const matching = pullRequests.filter(
66531
66659
  (pullRequest) => panel.update_workflows.some(
@@ -66542,7 +66670,7 @@ async function fetchGithubActionsPullRequestHealth(args) {
66542
66670
  event: "pull_request",
66543
66671
  requestHeaders: args.requestHeaders,
66544
66672
  fetcher: args.fetcher,
66545
- credentials: args.credentials ?? environmentCredentials()
66673
+ githubClient: githubClientFor(args)
66546
66674
  })
66547
66675
  }))
66548
66676
  );
@@ -66573,7 +66701,12 @@ async function fetchGithubActionsPullRequestHealth(args) {
66573
66701
  return {
66574
66702
  response: new Response(
66575
66703
  JSON.stringify(
66576
- errorEnvelope(panel.id, "upstream-error", error52, sourceLinkForRepository(source))
66704
+ errorEnvelope(
66705
+ panel.id,
66706
+ error52 instanceof GithubAuthenticationError ? "unauthorized" : "upstream-error",
66707
+ error52,
66708
+ sourceLinkForRepository(source)
66709
+ )
66577
66710
  ),
66578
66711
  { status: 200 }
66579
66712
  )
@@ -66581,9 +66714,8 @@ async function fetchGithubActionsPullRequestHealth(args) {
66581
66714
  }
66582
66715
  }
66583
66716
  async function latestRun(args) {
66584
- const call = githubRunsCall(args.source, args.workflow, args.branch, args.event, args.credentials);
66585
- forwardValidators(args.requestHeaders, call.headers);
66586
- const response = await args.fetcher(call.url, { headers: call.headers });
66717
+ const call = githubRunsCall(args.source, args.workflow, args.branch, args.event);
66718
+ const response = await githubFetch(call, args);
66587
66719
  if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
66588
66720
  const runs = runsSchema.parse(await response.json()).workflow_runs;
66589
66721
  return runs[0];
@@ -66591,43 +66723,30 @@ async function latestRun(args) {
66591
66723
  async function openPullRequests(args) {
66592
66724
  const result = [];
66593
66725
  for (let page = 1; ; page += 1) {
66594
- const call = pullRequestsCall(args.source, args.baseBranch, page, args.credentials);
66595
- forwardValidators(args.requestHeaders, call.headers);
66596
- const response = await args.fetcher(call.url, { headers: call.headers });
66726
+ const call = pullRequestsCall(args.source, args.baseBranch, page);
66727
+ const response = await githubFetch(call, args);
66597
66728
  if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
66598
66729
  const pageResults = pullRequestsSchema.parse(await response.json());
66599
66730
  result.push(...pageResults);
66600
66731
  if (pageResults.length < 100) return result;
66601
66732
  }
66602
66733
  }
66603
- function pullRequestsCall(source, baseBranch, page, credentials = environmentCredentials()) {
66734
+ function pullRequestsCall(source, baseBranch, page) {
66604
66735
  const url2 = new URL(`https://api.github.com/repos/${source.repo}/pulls`);
66605
66736
  url2.searchParams.set("state", "open");
66606
66737
  url2.searchParams.set("base", baseBranch);
66607
66738
  url2.searchParams.set("per_page", "100");
66608
66739
  url2.searchParams.set("page", String(page));
66609
- return { url: url2.toString(), headers: githubHeaders(source, credentials) };
66740
+ return { url: url2.toString(), headers: new Headers() };
66610
66741
  }
66611
- function githubHeaders(source, credentials) {
66612
- const headers = new Headers({ accept: "application/vnd.github+json" });
66613
- const token = source.token_env ? credentials.get(source.token_env) : void 0;
66614
- if (token) headers.set("authorization", `Bearer ${token}`);
66615
- return headers;
66616
- }
66617
- function githubRunsCall(source, workflow, branch, event, credentials = environmentCredentials()) {
66742
+ function githubRunsCall(source, workflow, branch, event) {
66618
66743
  const url2 = new URL(
66619
66744
  `https://api.github.com/repos/${source.repo}/actions/workflows/${encodeURIComponent(workflow)}/runs`
66620
66745
  );
66621
66746
  if (branch) url2.searchParams.set("branch", branch);
66622
66747
  if (event) url2.searchParams.set("event", event);
66623
66748
  url2.searchParams.set("per_page", "1");
66624
- return { url: url2.toString(), headers: githubHeaders(source, credentials) };
66625
- }
66626
- function forwardValidators(requestHeaders, target) {
66627
- for (const name of ["if-none-match", "if-modified-since"]) {
66628
- const value = requestHeaders.get(name);
66629
- if (value) target.set(name, value);
66630
- }
66749
+ return { url: url2.toString(), headers: new Headers() };
66631
66750
  }
66632
66751
  function healthItem(label, run, detail, link) {
66633
66752
  return {
@@ -66653,25 +66772,27 @@ function sourceLinkForRepository(source) {
66653
66772
  return `https://github.com/${source.repo}`;
66654
66773
  }
66655
66774
  async function fetchGithubActionsPipeline(args) {
66656
- const parsedSource = githubSourceSchema.parse(args.source);
66657
- const call = permittedGithubActionsCalls(
66658
- args.panel,
66659
- args.source,
66660
- args.credentials ?? environmentCredentials()
66661
- )[0];
66775
+ const parsedSource = githubActionsSourceSchema.parse(args.source);
66776
+ const call = permittedGithubActionsCalls(args.panel, args.source)[0];
66662
66777
  if (!call) throw new Error("GitHub Actions adapter declared no permitted call");
66663
- for (const name of ["if-none-match", "if-modified-since"]) {
66664
- const value = args.requestHeaders.get(name);
66665
- if (value) call.headers.set(name, value);
66666
- }
66667
66778
  let upstream;
66668
66779
  try {
66669
- upstream = await args.fetcher(call.url, { headers: call.headers });
66780
+ upstream = await githubFetch(call, {
66781
+ requestHeaders: args.requestHeaders,
66782
+ fetcher: args.fetcher,
66783
+ source: parsedSource,
66784
+ githubClient: githubClientFor(args)
66785
+ });
66670
66786
  } catch (error52) {
66671
66787
  return {
66672
66788
  response: new Response(
66673
66789
  JSON.stringify(
66674
- errorEnvelope(args.panel.id, "unreachable", error52, sourceLink(args.panel, args.source))
66790
+ errorEnvelope(
66791
+ args.panel.id,
66792
+ error52 instanceof GithubAuthenticationError ? "unauthorized" : "unreachable",
66793
+ error52,
66794
+ sourceLink(args.panel, args.source)
66795
+ )
66675
66796
  ),
66676
66797
  { status: 200 }
66677
66798
  )
@@ -66730,7 +66851,7 @@ async function fetchGithubActionsPipeline(args) {
66730
66851
  runId: run.id,
66731
66852
  requestHeaders: args.requestHeaders,
66732
66853
  fetcher: args.fetcher,
66733
- credentials: args.credentials ?? environmentCredentials()
66854
+ githubClient: githubClientFor(args)
66734
66855
  });
66735
66856
  if (activity) signal.activity = activity;
66736
66857
  }
@@ -66760,10 +66881,9 @@ async function fetchGithubActionsPipeline(args) {
66760
66881
  }
66761
66882
  }
66762
66883
  async function activeGithubActivity(args) {
66763
- const call = githubJobsCall(args.source, args.runId, args.credentials);
66764
- forwardValidators(args.requestHeaders, call.headers);
66884
+ const call = githubJobsCall(args.source, args.runId);
66765
66885
  try {
66766
- const response = await args.fetcher(call.url, { headers: call.headers });
66886
+ const response = await githubFetch(call, args);
66767
66887
  if (!response.ok) return void 0;
66768
66888
  const jobs = jobsSchema.parse(await response.json()).jobs;
66769
66889
  const job = jobs.find((candidate) => candidate.status === "in_progress") ?? jobs.find((candidate) => candidate.status === "queued");
@@ -66774,10 +66894,21 @@ async function activeGithubActivity(args) {
66774
66894
  return void 0;
66775
66895
  }
66776
66896
  }
66777
- function githubJobsCall(source, runId, credentials = environmentCredentials()) {
66897
+ async function githubFetch(call, args) {
66898
+ return args.githubClient.get({
66899
+ source: args.source,
66900
+ url: call.url,
66901
+ requestHeaders: args.requestHeaders,
66902
+ fetcher: args.fetcher
66903
+ });
66904
+ }
66905
+ function githubClientFor(args) {
66906
+ return args.githubClient ?? createGithubClient(args.credentials ?? environmentCredentials());
66907
+ }
66908
+ function githubJobsCall(source, runId) {
66778
66909
  const url2 = new URL(`https://api.github.com/repos/${source.repo}/actions/runs/${runId}/jobs`);
66779
66910
  url2.searchParams.set("per_page", "100");
66780
- return { url: url2.toString(), headers: githubHeaders(source, credentials) };
66911
+ return { url: url2.toString(), headers: new Headers() };
66781
66912
  }
66782
66913
  function completedRunDuration(run) {
66783
66914
  const startedAt = timestamp(run.run_started_at);
@@ -66813,7 +66944,7 @@ function errorEnvelope(panelId, kind, error52, link, observedAt3 = (/* @__PURE__
66813
66944
  }
66814
66945
  function sourceLink(panel, source) {
66815
66946
  const parsedPanel = pipelinePanelSchema.parse(panel);
66816
- const parsedSource = githubSourceSchema.parse(source);
66947
+ const parsedSource = githubActionsSourceSchema.parse(source);
66817
66948
  return `https://github.com/${parsedSource.repo}/actions/workflows/${encodeURIComponent(parsedPanel.pipeline)}`;
66818
66949
  }
66819
66950
  function observedAt(value) {
@@ -67026,6 +67157,7 @@ function createApp(deps) {
67026
67157
  const selectedBoard = config2.board ?? Object.keys(deps.boardConfig?.boards ?? {})[0] ?? "ze-great-team";
67027
67158
  const allowlist = deps.boardConfig ? deriveAllowlist(deps.boardConfig) : /* @__PURE__ */ new Map();
67028
67159
  const credentials = deps.credentials ?? environmentCredentials();
67160
+ const githubClient = createGithubClient(credentials);
67029
67161
  const app = new Hono2();
67030
67162
  app.get("/health", (c5) => c5.json({ status: "ok" }));
67031
67163
  app.use("/api/*", async (_c5, next) => next());
@@ -67096,7 +67228,7 @@ ${(0, import_yaml.stringify)(outputConfig, { sortMapEntries: true })}`,
67096
67228
  source,
67097
67229
  requestHeaders: c5.req.raw.headers,
67098
67230
  fetcher: deps.fetcher ?? globalThis.fetch,
67099
- credentials
67231
+ githubClient
67100
67232
  });
67101
67233
  const headers = passthroughHeaders(result.response.headers);
67102
67234
  if (result.response.status === 304) return new Response(null, { status: 304, headers });
@@ -67110,7 +67242,7 @@ ${(0, import_yaml.stringify)(outputConfig, { sortMapEntries: true })}`,
67110
67242
  source,
67111
67243
  requestHeaders: c5.req.raw.headers,
67112
67244
  fetcher: deps.fetcher ?? globalThis.fetch,
67113
- credentials
67245
+ githubClient
67114
67246
  });
67115
67247
  const headers = passthroughHeaders(result.response.headers);
67116
67248
  const envelope = result.envelope ?? JSON.parse(await result.response.text());
@@ -67265,7 +67397,7 @@ async function startup(options = {}) {
67265
67397
  ]);
67266
67398
  const board = selectBoard(config2.board, boardConfig);
67267
67399
  const resolvedConfig = { ...config2, board };
67268
- const credentialNames = Object.values(boardConfig.sources).map((source) => source.token_env).filter((name) => Boolean(name));
67400
+ const credentialNames = Object.values(boardConfig.sources).flatMap(credentialEnvironmentNames);
67269
67401
  const credentials = await createCredentialResolver({
67270
67402
  secretReference: config2.secretReference,
67271
67403
  credentialNames
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@continuous-excellence/ze-great-dashboard-aws",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
5
  "description": "AWS Lambda and CloudFormation adapter for Ze Great Dashboard.",
6
6
  "keywords": [
@@ -1,3 +0,0 @@
1
- import{z as e}from"zod";import{StrictMode as t,useEffect as n,useMemo as r,useRef as i,useState as a,useSyncExternalStore as o}from"react";import{createRoot as s}from"react-dom/client";import{Fragment as c,jsx as l,jsxs as u}from"react/jsx-runtime";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var d=/^(\d+)(ms|s|m|h)$/,f={ms:1,s:1e3,m:6e4,h:36e5};function p(e){let t=d.exec(e);if(!t)return null;let[,n,r]=t;if(n===void 0||r===void 0)return null;let i=Number(n);return i<=0?null:i*f[r]}var m=e.string().refine(e=>p(e)!==null,{message:`must be a positive duration like "30s", "5m", or "1h"`}).brand(),h=e.union([e.object({x:e.number().int().min(0),y:e.number().int().min(0),w:e.number().int().min(1).max(12),h:e.number().int().min(1)}),e.object({x:e.literal(0),y:e.literal(0),w:e.literal(0),h:e.literal(0)})]),g=e.enum([`auto`,`comfortable`,`compact`]),_=[`radial`,`runway`,`orbit`,`signal-field`,`telemetry-bloom`,`release-transit`,`status-weather`,`falling-shapes`],v=e.enum([..._,`off`]),ee=e.looseObject({label:e.string().min(1).optional(),id:e.string().min(1),type:e.string().min(1),source:e.string().min(1).optional(),pipeline:e.union([e.string(),e.number()]).optional(),branch:e.string().min(1).optional(),density:g.optional(),position:h.optional(),refresh:m.optional(),running_refresh:m.optional(),running_completion_refresh:m.optional(),running_completion_window:m.optional(),running_animation:v.optional(),demo_run_duration:m.optional(),demo_review_duration:m.optional(),link:e.url().optional(),url:e.url().optional(),json_path:e.string().regex(/^\$(?:\.[A-Za-z_][A-Za-z0-9_]*|\[\d+\])*$/,`must be a simple JSON path`).optional()}).superRefine((e,t)=>{`display`in e&&t.addIssue({code:`custom`,path:[`display`],message:`display was removed; use density`})}),y=e.looseObject({type:e.string().min(1),token_env:e.string().min(1).optional()}),b=e.object({refresh:m.optional(),running_refresh:m.optional(),running_completion_refresh:m.optional(),running_completion_window:m.optional(),panels:e.array(ee).min(1).superRefine((e,t)=>{let n=new Map;e.forEach((e,r)=>{let i=n.get(e.id);if(i===void 0){n.set(e.id,r);return}t.addIssue({code:`custom`,path:[r,`id`],message:`duplicate panel id "${e.id}" (already used by panel at index ${i})`})})})}),x=e.object({issuer:e.url(),client_id:e.string().min(1).optional(),allow:e.object({groups:e.array(e.string().min(1)).optional(),subjects:e.array(e.string().min(1)).optional()}).optional()});e.object({sources:e.record(e.string().min(1),y).default({}),boards:e.record(e.string().min(1),b),auth:x.optional()});var S=e.object({assetPath:e.string().min(1),proxyPath:e.string().min(1),board:e.string().min(1),clientVersion:e.string().min(1),auth:e.object({issuer:e.string().min(1),clientId:e.string().min(1).optional()}).optional()}),C=S.pick({assetPath:!0,clientVersion:!0});function w(t=globalThis.window?.env){let n=S.safeParse(t);if(!n.success)throw Error(`window.env is missing or invalid \u2014 the server did not inject usable configuration.
2
- ${e.prettifyError(n.error)}`);return n.data}var T=e.enum([`unreachable`,`unauthorized`,`not-found`,`no-runs`,`upstream-error`]),E=e.object({kind:T,message:e.string()}),te=e.discriminatedUnion(`state`,[e.object({panelId:e.string().min(1),state:e.literal(`ok`),observedAt:e.iso.datetime(),link:e.url().nullable(),signal:e.unknown()}),e.object({panelId:e.string().min(1),state:e.literal(`error`),observedAt:e.iso.datetime(),link:e.url().nullable(),error:E})]),ne=e.object({kind:e.enum([`job`,`stage`,`step`]),name:e.string().min(1),parent:e.string().min(1).optional()}),D=e.object({type:e.literal(`pipeline-status`),status:e.enum([`passed`,`failed`,`running`,`cancelled`,`unknown`]),rawStatus:e.string(),name:e.string().min(1),branch:e.string().min(1).optional(),durationMs:e.number().int().nonnegative().optional(),runStartedAt:e.iso.datetime().optional(),sourceRunId:e.string().min(1).optional(),activity:ne.optional(),estimatedDurationMs:e.number().int().positive().optional(),sourceUpdatedAt:e.iso.datetime().optional()}),re=e.object({label:e.string().min(1),status:D.shape.status,detail:e.string().min(1),link:e.url().nullable()}),ie=e.object({type:e.literal(`pull-request-health`),status:D.shape.status,summary:e.string().min(1),workflows:e.array(re),pullRequests:e.array(re)}),ae=e.object({type:e.literal(`http-value`),value:e.union([e.string(),e.number(),e.boolean()])}),oe=12,se=12;function ce(e){let t=e.flatMap(e=>!e.position||O(e.position)||le(e.position)?[]:[{panelId:e.id,kind:`out-of-bounds`,position:e.position,conflictsWith:[]}]),n=new Map;for(let r=0;r<e.length;r++){let i=e[r];if(!(!i?.position||O(i.position)))for(let a=r+1;a<e.length;a++){let r=e[a];if(!r?.position||O(r.position)||!ue(i.position,r.position))continue;let o=`${r.id}\0overlap`,s=n.get(o);if(s)s.conflictsWith.push(i.id);else{let e={panelId:r.id,kind:`overlap`,position:r.position,conflictsWith:[i.id]};n.set(o,e),t.push(e)}}}return{issues:t}}function O(e){return e?.x===0&&e.y===0&&e.w===0&&e.h===0}function le(e){return!O(e)&&e.x+e.w<=oe&&e.y+e.h<=se}function ue(e,t){return e.x<t.x+t.w&&e.x+e.w>t.x&&e.y<t.y+t.h&&e.y+e.h>t.y}var k={refreshMillis:6e4,runningRefreshMillis:15e3,runningCompletionRefreshMillis:5e3,runningCompletionWindowMillis:12e4};function de(e,t){let n=(e,t)=>p(e??``)??t,r=(r,i,a)=>n(t[r],n(e[i],a));return{refreshMillis:r(`refresh`,`refresh`,k.refreshMillis),runningRefreshMillis:r(`running_refresh`,`running_refresh`,k.runningRefreshMillis),runningCompletionRefreshMillis:r(`running_completion_refresh`,`running_completion_refresh`,k.runningCompletionRefreshMillis),runningCompletionWindowMillis:r(`running_completion_window`,`running_completion_window`,k.runningCompletionWindowMillis)}}var A={board:`_board_91ffc_1`,header:`_header_91ffc_11`,title:`_title_91ffc_18`,grid:`_grid_91ffc_24`,footerTools:`_footerTools_91ffc_34`,layoutWarning:`_layoutWarning_91ffc_39`,layoutWarningButton:`_layoutWarningButton_91ffc_42`,layoutWarningDialog:`_layoutWarningDialog_91ffc_60`,layoutWarningHeading:`_layoutWarningHeading_91ffc_73`,layoutWarningClose:`_layoutWarningClose_91ffc_91`,layoutWarningDownloads:`_layoutWarningDownloads_91ffc_99`,layoutWarningNote:`_layoutWarningNote_91ffc_118`,footer:`_footer_91ffc_34`},j={diagnostics:`_diagnostics_lseur_1`,button:`_button_lseur_5`,area:`_area_lseur_14`,warning:`_warning_lseur_31`,panels:`_panels_lseur_35`,actions:`_actions_lseur_43`};function fe({log:e}){let[t,n]=a(!1);o(e.subscribe,e.snapshot,e.snapshot);let r=e.count(),i=e.githubConsistencyIncidentCount(),s=e.summary();return u(`section`,{className:j.diagnostics,children:[u(`button`,{className:j.button,type:`button`,"aria-expanded":t,onClick:()=>n(!t),children:[`Diagnostics (`,r,`)`,i>0&&` · GitHub consistency ${i}`]}),t&&u(`div`,{className:j.area,children:[u(`p`,{children:[`Client `,e.clientVersion(),` · assets `,e.assetPath()]}),u(`p`,{children:[s.retained.eventCount,` retained browser-local events across`,` `,s.retained.sessionCount,` session`,s.retained.sessionCount===1?``:`s`,s.retained.firstEventAt&&s.retained.lastEventAt?` (${pe(s.retained.firstEventAt,s.retained.lastEventAt)})`:``,`. They are never uploaded.`]}),s.retained.evidenceMayBeIncomplete&&u(`p`,{className:j.warning,role:`alert`,children:[`Earlier evidence was pruned: `,s.retained.retention.eventsPrunedByCount,` at the 2,000-event cap and `,s.retained.retention.eventsPrunedByAge,` by the 7-day age limit. “No failures” applies only to the retained window.`]}),u(`p`,{children:[`Update failures: `,s.failures.clientUpdate,`; board fetch failures:`,` `,s.failures.boardFetch,`.`]}),e.githubConsistencyIncidentCount()>0&&u(`p`,{className:j.warning,role:`alert`,children:[`GitHub API consistency incidents: `,e.githubConsistencyIncidentCount(),`. A response older than the last accepted run was rejected; download diagnostics to report it.`]}),s.panels.length>0&&l(`div`,{className:j.panels,children:s.panels.map(e=>u(`p`,{children:[l(`strong`,{children:e.panelId}),` — `,e.requests,` requests`,Object.keys(e.httpStatuses).length?`; HTTP ${Object.entries(e.httpStatuses).map(([e,t])=>`${e}×${t}`).join(`, `)}`:``,`; parse/network failures `,e.parseFailures,`/`,e.networkFailures,`; visible changes `,e.visibleStateChanges,`; latest`,` `,e.latestRendered?`${e.latestRendered.state}${e.latestRendered.status?`/${e.latestRendered.status}`:``}`:`not rendered`,`.`]},e.panelId))}),u(`div`,{className:j.actions,children:[l(`button`,{className:j.button,type:`button`,onClick:()=>{let t=new Blob([JSON.stringify(e.export(),null,2)],{type:`application/json`}),n=URL.createObjectURL(t),r=document.createElement(`a`);r.href=n,r.download=`dashboard-diagnostics-${new Date().toISOString().replaceAll(`:`,`-`)}.json`,r.click(),URL.revokeObjectURL(n)},children:`Download`}),l(`button`,{className:j.button,type:`button`,onClick:()=>{window.confirm(`Clear this browser’s retained dashboard diagnostics?`)&&e.clear()},children:`Clear`})]})]})]})}function pe(e,t){return e===t?e:`${e} to ${t}`}function me(){try{return window.localStorage}catch{return}}function he(e,t){try{let n=e?.getItem(t);return n?JSON.parse(n):void 0}catch{return}}function ge(e,t,n){try{e?.setItem(t,JSON.stringify(n))}catch{}}function _e(e,t){try{e?.removeItem(t)}catch{}}function ve(e,t,n=0){let r=new Map,i=new Set,a=0,o=0;for(let t of e){if(i.add(t.sessionId),t.kind===`client-update-failure`&&a++,(t.kind===`board-fetch-failure`||t.kind===`board-fetch-parse-failure`)&&o++,!(`panelId`in t))continue;let e=r.get(t.panelId)??{panelId:t.panelId,requests:0,httpStatuses:{},parseFailures:0,networkFailures:0,visibleStateChanges:0};if(t.kind===`panel-fetch-start`&&e.requests++,t.kind===`panel-fetch-response`&&t.status!==void 0){let n=String(t.status);e.httpStatuses[n]=(e.httpStatuses[n]??0)+1}t.kind===`panel-fetch-parse-failure`&&e.parseFailures++,t.kind===`panel-fetch-failure`&&e.networkFailures++,t.kind===`panel-rendered`&&(e.visibleStateChanges++,e.latestRendered=t.rendered),r.set(t.panelId,e)}let s=e.map(e=>e.at).sort(),c=t.eventsPrunedByAge+t.eventsPrunedByCount;return{githubConsistencyIncidents:n,retained:{eventCount:e.length,firstEventAt:s[0],lastEventAt:s.at(-1),sessionCount:i.size,retention:t,evidenceMayBeIncomplete:c>0},failures:{clientUpdate:a,boardFetch:o},panels:[...r.values()].sort((e,t)=>e.panelId.localeCompare(t.panelId))}}var M=`ze-great-dashboard.diagnostics.v1`,ye=2e3,be=6048e5,xe=[`session-start`,`client-update-check`,`client-update-failure`,`client-update-detected`,`board-fetch-start`,`board-fetch-response`,`board-fetch-parse-failure`,`board-fetch-failure`,`layout-analyzed`,`panel-fetch-start`,`panel-fetch-response`,`panel-fetch-parse-failure`,`panel-fetch-failure`,`panel-rendered`],Se=class{env;storage;now;events=[];retention=N();revision=0;incidents=[];listeners=new Set;sessionId=crypto.randomUUID?.()??`${Date.now()}-${Math.random()}`;constructor(e,t=me(),n=()=>new Date){this.env=e,this.storage=t,this.now=n,this.events=this.read(),this.record({kind:`session-start`})}recordGithubConsistencyIncident(e){this.incidents.push({...e,at:this.now().toISOString(),board:this.env.board}),this.persist(),this.revision++,this.notify()}githubConsistencyIncidentCount=()=>this.incidents.length;record(e){let t=Ee([...this.events,{...e,schemaVersion:1,at:this.now().toISOString(),sessionId:this.sessionId,board:this.env.board}],this.now(),this.retention);this.events=t.events,this.retention=t.retention,this.persist(),this.revision++,this.notify()}count=()=>this.events.length;clientVersion=()=>this.env.clientVersion;assetPath=()=>this.env.assetPath;snapshot=()=>this.revision;summary=()=>ve(this.events,this.retention,this.incidents.length);clear(){this.events=[],this.incidents=[],this.retention=N(),_e(this.storage,M),this.revision++,this.notify()}subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)});export=()=>({schemaVersion:1,exportedAt:this.now().toISOString(),client:{version:this.env.clientVersion,assetPath:this.env.assetPath,board:this.env.board,sessionId:this.sessionId},events:this.events,githubConsistencyIncidents:this.incidents,summary:this.summary()});read(){let e=he(this.storage,M);if(!e||e.schemaVersion!==1||!Array.isArray(e.events)||!e.events.every(De))return _e(this.storage,M),[];let t=Ee(e.events.map(e=>({...e,schemaVersion:1})),this.now(),Te(e.retention));return this.retention=t.retention,this.incidents=Ce(e.githubConsistencyIncidents),t.events}persist(){ge(this.storage,M,{schemaVersion:1,events:this.events,retention:this.retention,githubConsistencyIncidents:this.incidents})}notify(){for(let e of this.listeners)e()}};function Ce(e){return Array.isArray(e)?e.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.at==`string`&&typeof t.board==`string`&&typeof t.panelId==`string`&&typeof t.endpoint==`string`&&!!t.accepted&&!!t.regressed&&!!t.response}):[]}function we(e){let t=Object.fromEntries([[`cacheControl`,`cache-control`],[`etag`,`etag`],[`lastModified`,`last-modified`],[`date`,`date`],[`age`,`age`]].flatMap(([t,n])=>{let r=e.get(n);return r?[[t,r]]:[]}));return Object.keys(t).length?t:void 0}function N(){return{eventsPrunedByAge:0,eventsPrunedByCount:0}}function Te(e){if(!e||typeof e!=`object`)return N();let t=e;return{eventsPrunedByAge:typeof t.eventsPrunedByAge==`number`&&t.eventsPrunedByAge>=0?t.eventsPrunedByAge:0,eventsPrunedByCount:typeof t.eventsPrunedByCount==`number`&&t.eventsPrunedByCount>=0?t.eventsPrunedByCount:0}}function Ee(e,t,n){let r=t.valueOf()-be,i=e.filter(e=>Number.isFinite(new Date(e.at).valueOf())&&new Date(e.at).valueOf()>=r),a=e.length-i.length,o=Math.max(0,i.length-ye);return{events:i.slice(-2e3),retention:{eventsPrunedByAge:n.eventsPrunedByAge+a,eventsPrunedByCount:n.eventsPrunedByCount+o}}}function De(e){if(!e||typeof e!=`object`)return!1;let t=e;return(t.schemaVersion===void 0||t.schemaVersion===1)&&typeof t.at==`string`&&Number.isFinite(new Date(t.at).valueOf())&&typeof t.sessionId==`string`&&typeof t.board==`string`&&xe.includes(t.kind)}var P={panel:`_panel_17ehh_1`,content:`_content_17ehh_21`,details:`_details_17ehh_34`,error:`_error_17ehh_42`,wide:`_wide_17ehh_45`,"density-comfortable":`_density-comfortable_17ehh_48`,"density-compact":`_density-compact_17ehh_55`,label:`_label_17ehh_65`,hint:`_hint_17ehh_76`,branch:`_branch_17ehh_82`,observed:`_observed_17ehh_86`,meta:`_meta_17ehh_92`,metaValue:`_metaValue_17ehh_95`,stale:`_stale_17ehh_99`,status:`_status_17ehh_102`,passed:`_passed_17ehh_110`,failed:`_failed_17ehh_113`,running:`_running_17ehh_116`,cancelled:`_cancelled_17ehh_119`,unknown:`_unknown_17ehh_120`,sourceAction:`_sourceAction_17ehh_123`,shallow:`_shallow_17ehh_153`,"density-auto":`_density-auto_17ehh_154`};function Oe({label:e,hint:t,wide:n=!1}){return u(`section`,{className:`${P.panel} ${n?P.wide:``}`,"data-panel":!0,"data-panel-id":`placeholder`,children:[l(`h2`,{className:P.label,children:e}),l(`p`,{className:P.hint,children:t})]})}var ke={fact:`_fact_envkl_1`};function Ae(e){let t=e.position;if(t)return{"--panel-column":`${t.x+1} / span ${t.w}`,"--panel-row":`${t.y+1} / span ${t.h}`}}function F({children:e,className:t}){return l(`p`,{className:`${P.hint} ${t??``}`,children:e})}function I({glyph:e,label:t,value:n,title:r,observed:i=!1,stale:a=!1,className:o}){return u(`p`,{className:`${P.hint} ${i?P.observed:``} ${a?P.stale:``} ${P.meta} ${o??``}`,"data-panel-meta":!0,children:[l(`span`,{"aria-hidden":`true`,children:e}),` `,u(`span`,{className:`screen-reader-only`,children:[t,`: `]}),l(`span`,{className:P.metaValue,title:r,children:n})]})}function L({children:e,status:t}){return l(`p`,{className:`${P.status} ${t?P[t]:``}`,children:e})}function R({panel:e,envelope:t,error:n=!1,field:r,children:i}){let a=e.density??`auto`,o=e.position,s=o!==void 0&&o.h<=2,c=o!==void 0&&o.h<=3;return u(`section`,{className:`${P.panel} ${P[`density-${a}`]} ${s?P.shallow:``} ${c?P.short:``} ${n?P.error:``}`,style:Ae(e),"aria-busy":!t||void 0,"data-panel":!0,"data-panel-id":e.id,"data-panel-position":o?`${o.x},${o.y},${o.w},${o.h}`:void 0,"data-density":a,"data-shallow":s,"data-short":c,"data-error":n||void 0,children:[r,l(je,{panelId:e.id,link:t?.link}),u(`div`,{className:P.content,"data-panel-content":!0,children:[l(`h2`,{className:P.label,children:e.label??e.id}),i]})]})}function je({panelId:e,link:t}){return t?u(`a`,{className:P.sourceAction,href:t,target:`_blank`,rel:`noopener noreferrer`,"aria-label":`View source for ${e} (opens in a new tab)`,title:`View source for ${e} (opens in a new tab)`,"data-panel-action":`source`,"data-panel-link":!0,children:[l(`span`,{"aria-hidden":`true`,children:`↗`}),l(`span`,{className:`screen-reader-only`,children:`View source`})]}):null}function z({value:e}){return l(Ne,{value:e,stale:!0,label:`Checked`,variant:`age`})}function Me({value:e,running:t}){return l(Ne,{value:e,label:t?`Started`:`Run updated`,variant:`age`})}function Ne({value:e,label:t,stale:n=!1,variant:r}){let i=new Date(e),a=i.toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`}),o=Date.now()-i.getTime(),s=r===`clock`?`${t} ${a} · ${Pe(o)}`:`${t} ${Pe(o)}`;return l(I,{glyph:`◷`,label:t,value:s,title:`${t} at ${a}`,observed:!0,stale:n})}function Pe(e){if(e<6e4)return`just now`;let t=Math.floor(e/6e4);return t<60?`${t}m ago`:`${Math.floor(t/60)}h ${t%60}m ago`}function Fe({panel:e,envelope:t,checkedAt:n}){if(!t)return l(R,{panel:e,children:l(F,{children:`Loading…`})});if(t.state===`error`)return u(R,{panel:e,envelope:t,error:!0,children:[l(L,{children:`⚠ Unable to read`}),l(F,{children:t.error.message}),n&&l(z,{value:n})]});let r=ae.safeParse(t.signal);return r.success?l(R,{panel:e,envelope:t,children:u(`div`,{className:ke.fact,children:[l(L,{children:String(r.data.value)}),n&&l(z,{value:n})]})}):u(R,{panel:e,envelope:t,error:!0,children:[l(L,{children:`⚠ Invalid value`}),n&&l(z,{value:n})]})}var Ie=.85,Le=[[{x:0,y:0},{x:1,y:0}],[{x:0,y:0},{x:0,y:1}],[{x:0,y:0},{x:1,y:0},{x:0,y:1}],[{x:0,y:0},{x:1,y:0},{x:2,y:0}],[{x:0,y:0},{x:0,y:1},{x:1,y:1}]];function Re(e,t){return e>t?`horizontal`:`vertical`}function ze(e,t=e===`horizontal`?12:3,n=e===`horizontal`?3:12){let r=Math.max(1,t*.8),i=Math.max(1,n*.8),a=Math.max(24,Math.min(42,Math.min(r,i)/4)),o=Math.max(3,Math.min(24,Math.round(r/a))),s=Math.max(3,Math.min(16,Math.round(i/a)));return e===`horizontal`?{columns:Math.max(o,s),rows:s}:{columns:o,rows:Math.max(s,o)}}function Be(e){return Array.from(e).reduce((e,t)=>e*31+t.charCodeAt(0)>>>0,7)}function Ve(e,t,n){let r=Math.max(...e.map(e=>e.x)),i=Math.max(...e.map(e=>e.y));return r<t&&i<n}function B(e,t){return e.cells.some(n=>t.cells.some(r=>e.x+n.x===t.x+r.x&&e.y+n.y===t.y+r.y))}function He(e,t,n){let r=Le.filter(e=>Ve(e,t,n));return r[V(e,r.length)]??[{x:0,y:0}]}function Ue(e,t,n,r,i,a=0,o=!1){let s=Math.max(...e.map(e=>e.x))+1,c=Math.max(...e.map(e=>e.y))+1,l=[];for(let a=0;a<=r-c;a++)for(let c=0;c<=n-s;c++){let s={id:-1,bornAt:0,cells:e,x:c,y:a,phase:`settled`};if(i.some(e=>B(s,e))||!Xe(e,t,n,r,s,i))continue;let u=t===`vertical`?e.filter(e=>a+e.y===r-1||i.some(t=>t.cells.some(n=>t.x+n.x===c+e.x&&t.y+n.y===a+e.y+1))).length:e.filter(e=>c+e.x===0||i.some(t=>t.cells.some(n=>t.x+n.x===c+e.x-1&&t.y+n.y===a+e.y))).length;o&&u<Ye(e,t)||l.push({x:c,y:a,support:u})}l.sort((e,n)=>n.support-e.support||(t===`vertical`?n.y-e.y||e.x-n.x:e.x-n.x||e.y-n.y));let u=l[0]?.support,d=l.filter(e=>e.support===u),f=d[V(a,d.length)];return f?{x:f.x,y:f.y}:void 0}function We(e,t,n,r,i,a){let o=Le.flatMap((o,s)=>{if(!Ve(o,t,n))return[];let c=Ue(o,e,t,n,r,i+s*31,a);return c?[{shape:o,destination:c}]:[]});if(o.length!==0)return o[V(i,o.length)]}function Ge(e,t,n){return Math.ceil(e*t*Ie*Math.min(1,Math.max(0,n)))}function Ke(e){return e.reduce((e,t)=>e+t.cells.length,0)}function qe(e,t,n,r,i){let a=e===`vertical`?n-1:0,o=new Set(r.flatMap(t=>t.cells.filter(n=>e===`vertical`?t.y+n.y===a:t.x+n.x===a).map(n=>e===`vertical`?t.x+n.x:t.y+n.y))),s=e===`vertical`?t:n,c=o.size===s;if(!c&&!i||o.size===0)return;let l=[];return{shapes:r.flatMap(t=>{let n=t.cells.filter(n=>{let r=e===`vertical`?t.y+n.y===a:t.x+n.x===a;return r&&l.push({x:t.x+n.x,y:t.y+n.y}),!r});return n.length===0?[]:[{...t,cells:n,y:e===`vertical`?t.y+1:t.y,x:e===`horizontal`?t.x-1:t.x}]}),cleared:l,complete:c}}function Je(e,t,n,r,i){let a=[];for(let o=0;o<i;o+=1){let i=r+o*17,s=He(i,t,n),c=Ue(s,e,t,n,a,i+1);if(!c)break;a.push({id:o,bornAt:0,cells:s,x:c.x,y:c.y,phase:`settled`})}return a}function Ye(e,t){return t===`vertical`?new Set(e.map(e=>e.x)).size:new Set(e.map(e=>e.y)).size}function Xe(e,t,n,r,i,a){let o=Math.max(...e.map(e=>e.x))+1,s=Math.max(...e.map(e=>e.y))+1;if(t===`vertical`){for(let e=0;e<=i.y;e+=1)if(a.some(t=>B({...i,y:e},t)))return!1;return i.y+s<=r}for(let e=n-o;e>=i.x;--e)if(a.some(t=>B({...i,x:e},t)))return!1;return i.x+o<=n}function V(e,t){if(t<=1)return 0;let n=Math.sin(e*12.9898+78.233)*43758.5453;return Math.floor((n-Math.floor(n))*t)}var Ze={variant:`_variant_1lsfm_1`},H={field:`_field_1x3vm_1`,grid:`_grid_1x3vm_10`,piece:`_piece_1x3vm_14`,cell:`_cell_1x3vm_34`,clearingCell:`_clearingCell_1x3vm_38`,"clear-cell":`_clear-cell_1x3vm_1`},Qe=50,U=1250,$e=250,et=850,tt=500;function nt({progress:e,estimatedDurationMs:t,overdue:r,seed:o=0}){let s=i(null),[c,d]=a({...ze(`vertical`),direction:`vertical`}),[f,p]=a([]),[m,h]=a(!1),[g,_]=a([]),[v,ee]=a(!1),y=i(c),b=i(c),x=i(e),S=i(o),C=i(void 0),w=i([]),T=i(!1),E=i({startedAt:Date.now(),nextPieceAt:U,recycleUntil:0,id:0,settled:[]});return n(()=>{x.current=e},[e]),n(()=>{S.current=o},[o]),n(()=>{let e=s.current;if(!e)return;let t=()=>{let t=e.getBoundingClientRect();t.width!==0&&t.height!==0&&d(e=>{let n=C.current??Re(t.width,t.height);C.current=n;let r={...ze(n,t.width,t.height),direction:n};return y.current=r,r})};if(t(),typeof ResizeObserver>`u`)return;let n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[]),n(()=>{let e=window.matchMedia(`(prefers-reduced-motion: reduce)`),t=()=>ee(e.matches);return t(),e.addEventListener?.(`change`,t),()=>e.removeEventListener?.(`change`,t)},[]),n(()=>{let e=b.current,t=e.direction!==c.direction||e.columns!==c.columns||e.rows!==c.rows;b.current=c,!(!t||v)&&(E.current={startedAt:Date.now(),nextPieceAt:U,id:0,recycleUntil:0,settled:[]},w.current=[],p([]),h(!1),_([]),T.current=!1)},[c,v]),n(()=>{if(!v)return;let e=Je(c.direction,c.columns,c.rows,S.current,Math.max(1,Math.floor(x.current*6)));w.current=e,E.current.settled=e,p(e)},[c,v]),n(()=>{if(v)return;let e=window.setInterval(()=>{let e=E.current,n=Date.now()-e.startedAt,i=y.current,a=x.current,o=Ge(i.columns,i.rows,a),s=[...e.settled],c=w.current.filter(e=>e.phase!==`settled`);if(n<e.recycleUntil)return;if(T.current&&(T.current=!1,h(!1),_([])),n>=e.nextPieceAt&&c.length===0){if(a<1&&Ke(s)>=o)return;let l=e.id,u=S.current+l*17,d=We(i.direction,i.columns,i.rows,s,u+1,!r);if(!d&&(a>=1||t===void 0)){let t=qe(i.direction,i.columns,i.rows,s,!0);if(t){s=t.shapes,e.settled=s,e.recycleUntil=n+tt,e.nextPieceAt=e.recycleUntil,w.current=s,T.current=!0,_(t.cleared),p(s),h(!0);return}}if(d){e.id+=1;let{shape:t,destination:r}=d,a=Math.max(...t.map(e=>e.y))+1;c=[...c,{id:l,bornAt:n,cells:t,x:i.direction===`horizontal`?i.columns-Math.max(...t.map(e=>e.x))-.5:r.x,y:i.direction===`vertical`?-a+.5:r.y,targetX:r.x,targetY:r.y,phase:`entry`}]}e.nextPieceAt+=rt(t,i)}c=c.map(e=>{let t=n-e.bornAt,r=e.targetX===void 0||e.targetY===void 0?void 0:{x:e.targetX,y:e.targetY};if(!r)return e;let a=Math.min(1,Math.max(0,(t-$e)/et));if(a>=1)return s=[...s,{...e,x:r.x,y:r.y,phase:`settled`}],{...e,x:r.x,y:r.y,phase:`settled`};let o=i.direction===`horizontal`?i.columns-Math.max(...e.cells.map(e=>e.x))-1:r.x,c=i.direction===`vertical`?0:r.y,l=Math.min(1,Math.max(0,t/1100));return{...e,x:i.direction===`horizontal`?o+(r.x-o)*a:o,y:i.direction===`vertical`?c+(r.y-c)*a:c,phase:t<$e?`entry`:l<.35?`align`:`travel`}}),e.settled=s;let l=[...s,...c.filter(e=>e.phase!==`settled`)];w.current=l,p(l)},Qe);return()=>window.clearInterval(e)},[t,r,v]),l(`div`,{ref:s,className:H.field,"data-running-part":`falling-shapes-field`,"data-overdue":r||void 0,"data-direction":c.direction,"data-recycling":m||void 0,style:{"--shape-columns":c.columns,"--shape-rows":c.rows},children:u(`div`,{className:H.grid,children:[g.map(e=>l(`span`,{className:H.clearingCell,style:{"--clear-x":e.x,"--clear-y":e.y}},`${e.x}-${e.y}`)),f.map(e=>l(`div`,{className:H.piece,"data-piece":e.id,"data-piece-phase":e.phase,style:{"--piece-x":e.x,"--piece-y":e.y,"--piece-width":Math.max(...e.cells.map(e=>e.x))+1,"--piece-height":Math.max(...e.cells.map(e=>e.y))+1},children:e.cells.map(e=>l(`span`,{className:H.cell,style:{"--cell-x":e.x,"--cell-y":e.y}},`${e.x}-${e.y}`))},e.id))]})})}function rt(e,t){let n=Math.ceil(t.columns*t.rows*.85);return e===void 0||n<=0?U:Math.max(400,e/Math.max(1,Math.ceil(n/3)))}var W={frontier:`_frontier_rnw91_1`,now:`_now_rnw91_12`,routes:`_routes_rnw91_20`,route:`_route_rnw91_20`,trail:`_trail_rnw91_41`,packet:`_packet_rnw91_42`,"packet-stall":`_packet-stall_rnw91_1`,"trail-backup":`_trail-backup_rnw91_1`};function it(){return u(c,{children:[l(`span`,{className:W.frontier,"data-running-part":`frontier`}),l(`span`,{className:W.now,"data-running-part":`transit-now`}),l(`span`,{className:W.routes,"data-running-part":`transit-routes`,children:[0,1,2].map(e=>l(`span`,{className:W.route},e))}),l(`span`,{className:W.trail,"data-running-part":`transit-trail`}),l(`span`,{className:W.packet,"data-running-part":`transit-packet`})]})}var G={field:`_field_1i9kx_1`,overdue:`_overdue_1i9kx_11`,timing:`_timing_1i9kx_14`,timingOverdue:`_timingOverdue_1i9kx_28`},K={haze:`_haze_3npie_1`,pressure:`_pressure_3npie_17`,band:`_band_3npie_20`,bandOne:`_bandOne_3npie_33`,bandTwo:`_bandTwo_3npie_36`,bandThree:`_bandThree_3npie_40`,drift:`_drift_3npie_45`,driftOne:`_driftOne_3npie_54`,driftTwo:`_driftTwo_3npie_58`,driftThree:`_driftThree_3npie_67`,driftFour:`_driftFour_3npie_76`,driftFive:`_driftFive_3npie_85`,"storm-band":`_storm-band_3npie_1`};function at(){return u(c,{children:[l(`span`,{className:K.haze,"data-running-part":`weather-haze`}),l(`span`,{className:K.pressure,"data-running-part":`weather-pressure`}),l(`span`,{className:`${K.band} ${K.bandOne}`}),l(`span`,{className:`${K.band} ${K.bandTwo}`}),l(`span`,{className:`${K.band} ${K.bandThree}`}),l(`span`,{className:`${K.drift} ${K.driftOne}`}),l(`span`,{className:`${K.drift} ${K.driftTwo}`}),l(`span`,{className:`${K.drift} ${K.driftThree}`}),l(`span`,{className:`${K.drift} ${K.driftFour}`}),l(`span`,{className:`${K.drift} ${K.driftFive}`})]})}var ot={anchor:`_anchor_1bd86_1`,body:`_body_1bd86_6`,"phased-marker":`_phased-marker_1bd86_1`};function st({anchorClassName:e,bodyClassName:t,delay:n,anchorPart:r,bodyPart:i}){let a=n?{"--phased-marker-delay":n}:void 0;return l(`span`,{className:`${ot.anchor} ${e??``}`,"data-running-part":r,children:l(`span`,{className:`${ot.body} ${t??``}`,"data-running-part":i,style:a})})}var q={frontier:`_frontier_2wwhn_1`,flare:`_flare_2wwhn_12`,lanes:`_lanes_2wwhn_15`,lane:`_lane_2wwhn_15`,markerAnchor:`_markerAnchor_2wwhn_31`,markerBody:`_markerBody_2wwhn_35`,"bloom-flare":`_bloom-flare_2wwhn_1`};function ct(){return u(c,{children:[l(`span`,{className:q.frontier,"data-running-part":`frontier`}),l(`span`,{className:q.flare,"data-running-part":`bloom-flare`}),l(`span`,{className:q.lanes,"data-running-part":`bloom-lanes`,children:[0,1,2,3].map(e=>l(`span`,{className:q.lane,"data-running-part":`bloom-lane`,children:l(st,{anchorClassName:q.markerAnchor,bodyClassName:q.markerBody,delay:[void 0,`-0.8s`,`-1.7s`,`-2.4s`][e],anchorPart:`bloom-marker-anchor`,bodyPart:`bloom-marker`})},e))})]})}function lt(e){return[`telemetry-bloom`,`release-transit`,`status-weather`,`falling-shapes`].includes(e)}function ut({animation:e,progress:t,estimatedDurationMs:n,overdue:r,indeterminate:i,seed:a}){let o={"--running-progress":`${t*100}%`};return u(`div`,{className:`${G.field} ${r?G.overdue:``}`,"data-animation":e,"data-running-field":!0,"data-overdue":r||void 0,"data-indeterminate":i||void 0,"aria-hidden":`true`,style:o,children:[e===`telemetry-bloom`&&l(ct,{}),e===`release-transit`&&l(it,{}),e===`status-weather`&&l(at,{}),e===`falling-shapes`&&l(nt,{progress:t,estimatedDurationMs:n,overdue:r,seed:a})]})}var dt=20;function ft(e,t){let n=pt(!!e),r=e?new Date(e).valueOf():NaN,i=Number.isFinite(r)?Math.max(0,n-r):void 0,a=i!==void 0&&t!==void 0;return{elapsedMs:i,estimatedDurationMs:t,hasEstimate:a,overdue:a&&i>t,progress:a?Math.min(i/t,1):0}}function pt(e){let[t,r]=a(()=>Date.now());return n(()=>{if(!e)return;r(Date.now());let t=window.setInterval(()=>r(Date.now()),dt);return()=>window.clearInterval(t)},[e]),t}function mt(e,t,n){return`${e===void 0?`Run in progress`:`Elapsed ${gt(e)}`} · ${t===void 0?`Expected duration unavailable`:`Expected ≈ ${gt(t)}`}${n?` · Over estimate`:``}`}function ht(e,t,n){let r=e===void 0?`—`:_t(e),i=t===void 0?`?`:`~${_t(t)}`;return`${n?`⚠`:`\xA0`}${r}/${i}`}function gt(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}function _t(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=`${r}:${String(i).padStart(2,`0`)}`;return n>0?`${n}:${a.padStart(5,`0`)}`:a}function vt({elapsedMs:e,estimatedDurationMs:t,overdue:n}){return u(`p`,{className:`${G.timing} ${n?G.timingOverdue:``}`,children:[l(`span`,{className:`screen-reader-only`,children:mt(e,t,n)}),l(`span`,{"aria-hidden":`true`,children:ht(e,t,n)})]})}var J={progress:`_progress_1x79l_1`,visual:`_visual_1x79l_8`,timing:`_timing_1x79l_12`,overdue:`_overdue_1x79l_17`,readout:`_readout_1x79l_23`,radial:`_radial_1x79l_31`,sweep:`_sweep_1x79l_1`,"alarm-ring":`_alarm-ring_1x79l_1`,radialCore:`_radialCore_1x79l_58`,"reactor-breathe":`_reactor-breathe_1x79l_1`,runway:`_runway_1x79l_70`,"barrier-pulse":`_barrier-pulse_1x79l_1`,spark:`_spark_1x79l_114`,sparkTwo:`_sparkTwo_1x79l_128`,orbit:`_orbit_1x79l_135`,orbitCore:`_orbitCore_1x79l_151`,particle:`_particle_1x79l_163`,particleTwo:`_particleTwo_1x79l_174`,"gravity-well":`_gravity-well_1x79l_1`,indeterminate:`_indeterminate_1x79l_191`,shift:`_shift_1x79l_1`,signalField:`_signalField_1x79l_199`,rail:`_rail_1x79l_217`,lead:`_lead_1x79l_223`,pulse:`_pulse_1x79l_233`,pulseTwo:`_pulseTwo_1x79l_244`,tracks:`_tracks_1x79l_247`,sparkWide:`_sparkWide_1x79l_1`,track:`_track_1x79l_247`,markerAnchor:`_markerAnchor_1x79l_371`,markerBody:`_markerBody_1x79l_375`,"endpoint-pulse":`_endpoint-pulse_1x79l_1`,short:`_short_1x79l_413`};function yt({animation:e,timing:t}){let{elapsedMs:n,estimatedDurationMs:r,hasEstimate:i,overdue:a,progress:o}=t,s=e===`runway`||e===`signal-field`,d=mt(n,r,a),f={"--running-progress":`${o*100}%`,"--running-degrees":`${o*360}deg`},p=e===`signal-field`?J.signalField:J[e];return u(`div`,{className:`${J.progress} ${p} ${a?J.overdue:``} ${i?``:J.indeterminate}`,style:f,"data-running-progress":e,"data-overdue":a||void 0,"data-indeterminate":!i||void 0,children:[u(`div`,{className:J.visual,"aria-hidden":`true`,"data-running-visual":!0,children:[e===`radial`&&l(`span`,{className:J.radialCore}),e===`runway`&&u(c,{children:[l(`span`,{className:J.spark,"data-running-part":`runway-spark`}),l(`span`,{className:`${J.spark} ${J.sparkTwo}`,"data-running-part":`runway-spark-two`})]}),e===`orbit`&&u(c,{children:[l(`span`,{className:J.orbitCore}),l(`span`,{className:J.particle}),l(`span`,{className:`${J.particle} ${J.particleTwo}`})]}),e===`signal-field`&&u(c,{children:[l(`span`,{className:J.rail}),l(`span`,{className:J.lead}),l(`span`,{className:J.pulse}),l(`span`,{className:`${J.pulse} ${J.pulseTwo}`}),l(`span`,{className:J.tracks,"data-running-part":`signal-tracks`,children:[0,1,2,3,4].map(e=>l(`span`,{className:J.track,"data-running-part":`signal-track`,children:l(st,{anchorClassName:J.markerAnchor,bodyClassName:J.markerBody,delay:[void 0,`-0.8s`,`-1.7s`,`-2.4s`,`-0.35s`][e],anchorPart:`signal-marker-anchor`,bodyPart:`signal-marker`})},e))})]})]}),l(`p`,{className:`${J.timing} ${s?J.readout:``}`,children:s?u(c,{children:[l(`span`,{className:`screen-reader-only`,children:d}),l(`span`,{"aria-hidden":`true`,children:ht(n,r,a)})]}):d})]})}function bt(e){return[`radial`,`runway`,`orbit`,`signal-field`].includes(e)}var xt=2e4,St=15e3,Ct=3e5,wt=1.25,Tt=[`radial`,`runway`,`orbit`,`signal-field`,`telemetry-bloom`,`release-transit`,`status-weather`,`falling-shapes`];function Et({panel:e}){let t=kt(),n=e.running_animation===void 0||e.running_animation===`off`?void 0:e.running_animation,r=Dt(e.demo_run_duration,xt),i=Dt(e.demo_review_duration,Ct),a=n?Math.ceil(i*wt):r,o=Math.floor(t/a),s=n??Tt[o%Tt.length]??`radial`,c=o*a;return l(Ot,{panel:e,animation:s,runStartedAt:c,estimatedDurationMs:n?i:St})}function Dt(e,t){return e?p(e)??t:t}function Ot({panel:e,animation:t,runStartedAt:n,estimatedDurationMs:r}){let i=ft(new Date(n).toISOString(),r),a=lt(t);return u(R,{panel:e,field:a?l(ut,{animation:t,progress:i.progress,estimatedDurationMs:i.estimatedDurationMs,overdue:i.overdue,indeterminate:!i.hasEstimate,seed:Be(e.id)},`${t}-${n}`):void 0,children:[l(L,{status:`running`,children:`↻ Running`}),u(`p`,{className:Ze.variant,children:[`Demo treatment · `,t]}),a?l(vt,{elapsedMs:i.elapsedMs,estimatedDurationMs:r,overdue:i.overdue}):l(yt,{animation:t,timing:i})]})}function kt(){let[e,t]=a(()=>Date.now());return n(()=>{let e=window.setInterval(()=>t(Date.now()),1e3);return()=>window.clearInterval(e)},[]),e}var Y={details:`_details_19avj_1`,activity:`_activity_19avj_7`,duration:`_duration_19avj_8`};function At(e){return e?e.parent?`${e.parent} › ${e.name}`:e.name:`Activity unavailable`}function jt({panel:e,envelope:t,checkedAt:n}){if(!t)return l(R,{panel:e,children:l(F,{children:`Loading…`})});if(t.state===`error`)return u(R,{panel:e,envelope:t,error:!0,children:[u(L,{children:[`⚠ `,t.error.kind===`no-runs`?`No workflow runs`:`Unable to read`]}),l(F,{children:t.error.message}),n&&l(z,{value:n})]});let r=D.safeParse(t.signal);return r.success?l(Mt,{panel:e,envelope:t,signal:r.data,checkedAt:n}):u(R,{panel:e,envelope:t,error:!0,children:[l(L,{children:`⚠ Invalid signal`}),n&&l(z,{value:n})]})}function Mt({panel:e,envelope:t,signal:n,checkedAt:r}){let o=Ft(n.status),[s,c]=a(()=>n.status===`running`?Nt():void 0),d=i(n.status);if(n.status!==d.current){let t=d.current===`running`;d.current=n.status,e.running_animation===void 0&&!t&&n.status===`running`&&c(e=>Nt(e))}let f=e.running_animation??s??`off`,p=n.status===`running`&&f!==`off`,m=ft(n.runStartedAt,n.estimatedDurationMs),h=p&&lt(f),g=p&&bt(f);return l(R,{panel:e,envelope:t,field:h?l(ut,{animation:f,progress:m.progress,estimatedDurationMs:m.estimatedDurationMs,overdue:m.overdue,indeterminate:!m.hasEstimate,seed:Be(e.id)}):void 0,children:u(`div`,{className:Y.details,children:[u(L,{status:n.status,children:[o.glyph,` `,o.label]}),n.status===`running`&&l(I,{glyph:`⚙`,label:`Activity`,value:At(n.activity),title:`Activity: ${At(n.activity)}`,className:Y.activity}),n.branch&&l(I,{glyph:`⎇`,label:`Branch`,value:l(`span`,{className:Y.branch,children:n.branch}),title:`Branch: ${n.branch}`}),h&&l(vt,{elapsedMs:m.elapsedMs,estimatedDurationMs:n.estimatedDurationMs,overdue:m.overdue}),g&&l(yt,{animation:f,timing:m}),n.status!==`running`&&n.durationMs!==void 0&&l(I,{glyph:`◷`,label:`Duration`,value:`Took ${Pt(n.durationMs)}`,title:`Duration: Took ${Pt(n.durationMs)}`,className:Y.duration}),(n.status===`running`&&n.runStartedAt||n.sourceUpdatedAt)&&l(Me,{value:n.status===`running`&&n.runStartedAt?n.runStartedAt:n.sourceUpdatedAt??t.observedAt,running:n.status===`running`}),r&&l(z,{value:r})]})})}function Nt(e){let t=_.filter(t=>t!==e);return t[Math.floor(Math.random()*t.length)]??`telemetry-bloom`}function Pt(e){let t=Math.floor(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60;return n>0?`${n}h ${r}m`:r>0?`${r}m ${i}s`:`${i}s`}function Ft(e){switch(e){case`passed`:return{glyph:`✓`,label:`Passed`};case`failed`:return{glyph:`✕`,label:`Failed`};case`running`:return{glyph:`↻`,label:`Running`};case`cancelled`:return{glyph:`⊘`,label:`Cancelled`};case`unknown`:return{glyph:`?`,label:`Unknown`}}}function It({panel:e,envelope:t,checkedAt:n}){if(!t)return l(R,{panel:e,children:l(F,{children:`Loading…`})});if(t.state===`error`)return u(R,{panel:e,envelope:t,error:!0,children:[l(L,{children:`⚠ Unable to read`}),l(F,{children:t.error.message}),n&&l(z,{value:n})]});let r=ie.safeParse(t.signal);if(!r.success)return l(R,{panel:e,envelope:t,error:!0,children:l(L,{children:`⚠ Invalid signal`})});let i=Lt(r.data.status);return u(R,{panel:e,envelope:t,children:[u(L,{status:r.data.status,children:[i.glyph,` `,i.label]}),l(F,{children:r.data.summary}),n&&l(z,{value:n})]})}function Lt(e){switch(e){case`passed`:return{glyph:`✓`,label:`Healthy`};case`failed`:return{glyph:`✕`,label:`Failed`};case`running`:return{glyph:`↻`,label:`Running`};case`cancelled`:return{glyph:`⊘`,label:`Cancelled`};case`unknown`:return{glyph:`?`,label:`Unknown`}}}var Rt={"pipeline-status":jt,"pull-request-health":It,"http-value":Fe,"pipeline-animation-demo":Et};function zt({panel:e,envelope:t,checkedAt:n}){let r=Rt[e.type];return r?l(r,{panel:e,envelope:t,checkedAt:n}):l(Oe,{label:e.type,hint:`Not wired yet`,wide:!0})}var Bt=6e4,Vt=1e4,Ht=()=>globalThis.window.location.reload();function Ut({env:e,diagnostics:t,fetcher:r,reload:i=Ht}){n(()=>{let n=!1,a=!1,o,s=`${e.proxyPath}/client`,c=async()=>{if(n||a)return;a=!0;let l=new AbortController;o=l;let u=globalThis.setTimeout(()=>l.abort(),Vt);t.record({kind:`client-update-check`,path:s});try{let a=await(r??globalThis.fetch)(s,{cache:`no-store`,signal:l.signal});if(!a.ok)throw Error(`Client identity returned ${a.status}`);let o=C.safeParse(await a.json());if(!o.success)throw Error(`Client identity response was invalid`);if(n)return;o.data.assetPath!==e.assetPath&&(t.record({kind:`client-update-detected`,path:s,current:{assetPath:e.assetPath,clientVersion:e.clientVersion},next:o.data}),i())}catch(e){!n&&!(e instanceof DOMException&&e.name===`AbortError`)&&t.record({kind:`client-update-failure`,path:s,message:e instanceof Error?e.message:String(e)})}finally{globalThis.clearTimeout(u),a=!1,o===l&&(o=void 0),n||globalThis.setTimeout(()=>void c(),Bt)}};return c(),()=>{n=!0,o?.abort()}},[t,e.assetPath,e.clientVersion,e.proxyPath,r,i])}function X(e,t){if(t.state===`error`)return{state:t.state,link:t.link};if(e.type===`pipeline-status`){let e=D.safeParse(t.signal);return{state:t.state,status:e.success?e.data.status:void 0,link:t.link}}if(e.type===`pull-request-health`){let e=ie.safeParse(t.signal);return{state:t.state,status:e.success?e.data.status:void 0,link:t.link}}return{state:t.state,link:t.link}}function Wt(e,t,n){if(!e)return!0;let r=X(t,e),i=X(t,n);return r.state!==i.state||r.status!==i.status||r.link!==i.link}var Gt=`ze-great-dashboard.panel-memory.v1`,Kt=1,qt=12096e5,Jt=class{now;histories;storage;constructor(e=me(),t=()=>new Date){this.now=t,this.storage=e,this.histories=this.read(),this.pruneAll()}latest(e){return this.history(e).latest}rememberLatest(e,t){this.history(e).latest=t,this.persist()}recordRun(e,t,n=!1){let r=this.history(e);n&&(r.durations[Yt(t)]=t);let i=r.latestCompleted;(!i||Xt(t.sourceUpdatedAt,i.sourceUpdatedAt))&&(r.latestCompleted=t),this.pruneHistory(r),this.persist()}recordSuccessfulRun(e,t){this.recordRun(e,t,!0)}recordCompletedRun(e,t){this.recordRun(e,t)}medianDuration(e){let t=this.history(e);this.pruneHistory(t);let n=Object.values(t.durations).map(({durationMs:e})=>e).sort((e,t)=>e-t);if(n.length===0)return;let r=Math.floor(n.length/2);if(n.length%2==1)return n[r];let i=n[r-1],a=n[r];return i===void 0||a===void 0?void 0:Math.floor((i+a)/2)}resolveEstimatedDuration(e){let t=this.medianDuration(e);if(t!==void 0)return t;let n=this.history(e);return this.pruneHistory(n),n.latestCompleted?.durationMs}history(e){let t=Qt(e),n=this.histories[t];if(n)return n;let r={durations:{}};return this.histories[t]=r,r}pruneAll(){for(let e of Object.values(this.histories))this.pruneHistory(e);this.persist()}pruneHistory(e){let t=this.now().valueOf()-qt;for(let[n,r]of Object.entries(e.durations)){let i=Z(r.sourceUpdatedAt);(i===void 0||i<t)&&delete e.durations[n]}let n=e.latestCompleted?Z(e.latestCompleted.sourceUpdatedAt):void 0;e.latestCompleted&&(n===void 0||n<t)&&delete e.latestCompleted}read(){let e=he(this.storage,Gt);return e?.schemaVersion!==Kt||!e.histories?{}:$t(e.histories)?e.histories:{}}persist(){ge(this.storage,Gt,{schemaVersion:Kt,histories:this.histories})}};function Yt(e){return e.sourceRunId??e.link??e.sourceUpdatedAt}function Xt(e,t){let n=Z(e),r=Z(t);return n!==void 0&&(r===void 0||n>=r)}function Z(e){let t=Date.parse(e);return Number.isFinite(t)?t:void 0}function Zt(e,t){return{board:e,panelId:t.id,source:t.source??``,workflow:typeof t.pipeline==`string`||typeof t.pipeline==`number`?String(t.pipeline):``,branch:t.branch??``}}function Qt(e){return JSON.stringify([e.board,e.panelId,e.source,e.workflow,e.branch])}function $t(e){return Q(e)?Object.values(e).every(en):!1}function en(e){return!Q(e)||!Q(e.durations)||!Object.values(e.durations).every(tn)?!1:e.latestCompleted===void 0||tn(e.latestCompleted)}function tn(e){return Q(e)?(typeof e.link==`string`||e.link===null)&&(e.sourceRunId===void 0||typeof e.sourceRunId==`string`)&&typeof e.durationMs==`number`&&Number.isInteger(e.durationMs)&&e.durationMs>=0&&typeof e.sourceUpdatedAt==`string`&&Z(e.sourceUpdatedAt)!==void 0:!1}function Q(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function nn(e){let t=rn(e.envelope);if(!t)return{kind:`not-pipeline`,envelope:e.envelope};if(e.accepted&&t.sourceUpdatedAt&&Date.parse(t.sourceUpdatedAt)<Date.parse(e.accepted.sourceUpdatedAt))return e.envelope.state!==`ok`||!t.sourceUpdatedAt?{kind:`not-pipeline`,envelope:e.envelope}:{kind:`rejected`,envelope:e.envelope,signal:{...t,sourceUpdatedAt:t.sourceUpdatedAt}};let n=t.sourceUpdatedAt?{sourceUpdatedAt:t.sourceUpdatedAt,status:t.status,link:e.envelope.link}:void 0,r=t.status!==`running`&&t.durationMs!==void 0&&t.sourceUpdatedAt&&Number.isFinite(Date.parse(t.sourceUpdatedAt))?{link:e.envelope.link,...t.sourceRunId?{sourceRunId:t.sourceRunId}:{},durationMs:t.durationMs,sourceUpdatedAt:t.sourceUpdatedAt}:void 0;return{kind:`accepted`,envelope:t.status===`running`&&e.estimatedDurationMs!==void 0&&e.envelope.state===`ok`?{...e.envelope,signal:{...t,estimatedDurationMs:e.estimatedDurationMs}}:e.envelope,signal:t,accepted:n,durationSample:r}}function rn(e){if(e.state!==`ok`)return;let t=D.safeParse(e.signal);return t.success?t.data:void 0}function an(e,t,n){let r=on(e);if(!r)return n.refreshMillis;let i=sn(r);return i===void 0?n.runningRefreshMillis:t<i?Math.min(n.runningRefreshMillis,i-t):t<i+n.runningCompletionWindowMillis?n.runningCompletionRefreshMillis:n.runningRefreshMillis}function on(e){if(e?.state!==`ok`)return;let t=D.safeParse(e.signal);return t.success&&t.data.status===`running`?t.data:void 0}function sn(e){if(!e.runStartedAt||e.estimatedDurationMs===void 0)return;let t=Date.parse(e.runStartedAt);return Number.isFinite(t)?t+e.estimatedDurationMs:void 0}function cn({board:e,env:t,diagnostics:r,memory:o}){let[s,c]=a({}),[l,u]=a({}),d=i({}),f=i(null);return f.current||=o??new Jt,n(()=>{if(d.current={},c({}),u({}),!e)return;let n=!1,i=new Set;for(let a of e.panels){if(O(a.position)||a.type!==`pipeline-status`&&a.type!==`pull-request-health`&&a.type!==`http-value`)continue;let o=!1,s=f.current;if(!s)return;let l=de(e,a),p=`${t.proxyPath}/panel/${encodeURIComponent(t.board)}/${encodeURIComponent(a.id)}`,m,h=()=>{n||o||(o=!0,r.record({kind:`panel-fetch-start`,panelId:a.id,path:p}),fetch(p).then(async e=>{n||u(e=>({...e,[a.id]:new Date().toISOString()}));let t={kind:`panel-fetch-response`,panelId:a.id,path:p,status:e.status,cache:we(e.headers)};if(e.status===304){r.record(t);return}try{let n=dn(await e.json());if(!n){r.record(t),r.record({kind:`panel-fetch-parse-failure`,panelId:a.id,path:p,message:`Response was not a valid signal envelope.`});return}return r.record({...t,envelope:n}),{envelope:n,cache:t.cache,status:e.status}}catch(e){throw r.record(t),r.record({kind:`panel-fetch-parse-failure`,panelId:a.id,path:p,message:ln(e)}),new un(e)}}).then(e=>{if(!e)return;let i=e.envelope;if(a.type===`pipeline-status`){let n=Zt(t.board,a),o=s.latest(n),c=nn({envelope:i,accepted:o,estimatedDurationMs:s.resolveEstimatedDuration(n)});if(c.kind===`rejected`&&o){let t=c.signal;r.recordGithubConsistencyIncident({panelId:a.id,endpoint:p,identity:{source:n.source,workflow:n.workflow,branch:n.branch},accepted:o,regressed:{sourceUpdatedAt:t.sourceUpdatedAt,status:t.status,link:i.link},response:{httpStatus:e.status,date:e.cache?.date,etag:e.cache?.etag,cacheControl:e.cache?.cacheControl}});return}if(c.kind===`accepted`&&(i=c.envelope,c.accepted&&s.rememberLatest(n,c.accepted),c.durationSample)){let e={link:c.durationSample.link,...c.durationSample.sourceRunId?{sourceRunId:c.durationSample.sourceRunId}:{},durationMs:c.durationSample.durationMs,sourceUpdatedAt:c.durationSample.sourceUpdatedAt};s.recordRun(n,e,c.signal.status===`passed`)}}if(m=i,!n){let e=d.current[a.id];Wt(e,a,i)&&r.record({kind:`panel-rendered`,panelId:a.id,path:p,rendered:X(a,i)}),d.current={...d.current,[a.id]:i},c(d.current)}}).catch(e=>{e instanceof un||r.record({kind:`panel-fetch-failure`,panelId:a.id,path:p,message:ln(e)})}).finally(()=>{if(o=!1,!n){let e=window.setTimeout(()=>{i.delete(e),h()},an(m,Date.now(),l));i.add(e)}}))};h()}return()=>{n=!0;for(let e of i)window.clearTimeout(e)}},[e,r,t.board,t.proxyPath]),{signals:s,checkedAt:l}}function ln(e){return e instanceof Error?e.message:String(e)}var un=class extends Error{constructor(e){super(ln(e))}};function dn(e){let t=te.safeParse(e);return t.success?t.data:void 0}function fn({env:e}){let[t,o]=a(),[s,c]=a(),d=i(null);d.current||=new Se(e);let f=d.current;Ut({env:e,diagnostics:f});let{signals:p,checkedAt:m}=cn({board:s===e.board?t:void 0,env:e,diagnostics:f}),h=r(()=>t?ce(t.panels):void 0,[t]);return n(()=>{!h||h.issues.length===0||f.record({kind:`layout-analyzed`,issueCount:h.issues.length,affectedPanelIds:h.issues.map(e=>e.panelId)})},[f,h]),n(()=>{let t=!1;o(void 0),c(void 0);let n=`${e.proxyPath}/boards/${encodeURIComponent(e.board)}`;return f.record({kind:`board-fetch-start`,path:n}),fetch(n).then(async e=>{if(f.record({kind:`board-fetch-response`,path:n,status:e.status,cache:we(e.headers)}),!e.ok)throw Error(`Board configuration returned ${e.status}`);try{return await e.json()}catch(e){throw f.record({kind:`board-fetch-parse-failure`,path:n,message:$(e)}),new mn(e)}}).then(r=>{if(!t){o(r),c(e.board);let t=Array.isArray(r.panels)?r.panels:[];f.record({kind:`board-fetch-response`,path:n,boardSummary:{panelCount:t.length,panelIds:t.flatMap(e=>typeof e.id==`string`?[e.id]:[])}})}}).catch(r=>{r instanceof mn||f.record({kind:`board-fetch-failure`,path:n,message:$(r)}),t||(o({panels:[]}),c(e.board))}),()=>{t=!0}},[f,e.board,e.proxyPath]),u(`div`,{className:A.board,children:[l(`header`,{className:A.header,children:l(`h1`,{className:A.title,children:e.board})}),u(`main`,{className:A.grid,children:[!t&&l(Oe,{label:`board`,hint:`Loading configuration…`,wide:!0}),t?.panels.filter(e=>!O(e.position)).map(e=>l(zt,{panel:e,envelope:p[e.id],checkedAt:m[e.id]},e.id))]}),u(`footer`,{className:A.footer,"data-board-footer":!0,children:[l(`span`,{children:`Signals are read live from their configured authorities.`}),u(`div`,{className:A.footerTools,children:[h&&h.issues.length>0&&l(pn,{board:e.board,layout:h,proxyPath:e.proxyPath}),l(fe,{log:f})]})]})]})}function pn({board:e,layout:t,proxyPath:r}){let[i,o]=a(!1),s=`layout-warning-${e}`;n(()=>{if(!i)return;let e=e=>{e.key===`Escape`&&o(!1)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[i]);let c=`${r}/boards/${encodeURIComponent(e)}`;return u(`div`,{className:A.layoutWarning,"data-layout-warning":!0,children:[u(`button`,{className:A.layoutWarningButton,type:`button`,"aria-label":`Layout warnings (${t.issues.length})`,"aria-expanded":i,"aria-controls":s,onClick:()=>o(!i),children:[l(`span`,{"aria-hidden":`true`,children:`⚠`}),l(`span`,{children:t.issues.length})]}),i&&u(`aside`,{className:A.layoutWarningDialog,id:s,role:`dialog`,"aria-labelledby":`${s}-title`,"aria-modal":`false`,children:[u(`div`,{className:A.layoutWarningHeading,children:[l(`strong`,{id:`${s}-title`,children:`Layout warnings`}),l(`button`,{className:A.layoutWarningClose,type:`button`,"aria-label":`Close layout warnings`,onClick:()=>o(!1),children:`×`})]}),u(`p`,{children:[t.issues.length,` layout issue`,t.issues.length===1?``:`s`,` detected against the intended 12×12 space. The live board is unchanged: explicit overlaps remain overlapped and overflow continues in implicit rows.`]}),l(`ul`,{children:t.issues.map(e=>u(`li`,{children:[l(`strong`,{children:e.panelId}),`: `,e.kind,` at (`,e.position.x,`,`,` `,e.position.y,`), `,e.position.w,`×`,e.position.h,e.conflictsWith.length?`; overlaps ${e.conflictsWith.join(`, `)}`:``]},`${e.panelId}-${e.kind}`))}),u(`div`,{className:A.layoutWarningDownloads,children:[l(`a`,{href:`${c}/rendered`,download:`${e}-layout-rendered.yaml`,children:`Download legal rendered layout`}),l(`a`,{href:`${c}/authored`,download:`${e}-layout-authored.yaml`,children:`Download authored layout`})]}),l(`p`,{className:A.layoutWarningNote,children:`The legal rendered layout normalizes the currently visible explicit area into 12×12 and makes the smallest deterministic adjustments needed to avoid collisions. The authored layout preserves the original coordinates exactly.`})]})]})}function $(e){return e instanceof Error?e.message:String(e)}var mn=class extends Error{constructor(e){super($(e))}},hn={error:`_error_yx1g9_1`};function gn({message:e}){return u(`div`,{className:hn.error,role:`alert`,children:[l(`h1`,{children:`⚠️ Dashboard misconfigured`}),l(`p`,{children:`The page loaded, but the server did not hand it usable configuration.`}),l(`pre`,{children:e})]})}var _n=document.getElementById(`root`);if(!_n)throw Error(`No #root element in the document — the template is not the one we expect.`);var vn=s(_n);try{vn.render(l(t,{children:l(fn,{env:w()})}))}catch(e){vn.render(l(gn,{message:e instanceof Error?e.message:String(e)}))}
3
- //# sourceMappingURL=index-CSO187vo.js.map