@wenathlan/extension 1.1.61 → 1.1.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +4 -3
  2. package/dist/confirmgates.d.ts +60 -0
  3. package/dist/confirmgates.d.ts.map +1 -0
  4. package/dist/inboundguard.d.ts +86 -0
  5. package/dist/inboundguard.d.ts.map +1 -0
  6. package/dist/index.d.ts +7 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +747 -3
  9. package/dist/index.js.map +4 -4
  10. package/dist/memory.d.ts +89 -1
  11. package/dist/memory.d.ts.map +1 -1
  12. package/dist/originpolicy.d.ts +10 -0
  13. package/dist/originpolicy.d.ts.map +1 -1
  14. package/dist/phishguard.d.ts +24 -0
  15. package/dist/phishguard.d.ts.map +1 -0
  16. package/dist/policy.d.ts +68 -1
  17. package/dist/policy.d.ts.map +1 -1
  18. package/dist/protocol.d.ts +88 -0
  19. package/dist/protocol.d.ts.map +1 -1
  20. package/dist/redactshots.d.ts +54 -0
  21. package/dist/redactshots.d.ts.map +1 -0
  22. package/dist/secretvault.d.ts +89 -0
  23. package/dist/secretvault.d.ts.map +1 -0
  24. package/dist/transparency.d.ts +46 -0
  25. package/dist/transparency.d.ts.map +1 -0
  26. package/dist/types.d.ts +173 -3
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/version.d.ts +1 -1
  29. package/extension/dist/background.js +984 -54
  30. package/extension/dist/background.js.map +4 -4
  31. package/extension/dist/manifest.json +5 -1
  32. package/extension/dist/pagebridge.js.map +2 -2
  33. package/extension/dist/popup.html +1 -1
  34. package/extension/dist/popup.js +15 -0
  35. package/extension/dist/popup.js.map +2 -2
  36. package/extension/dist/sidepanel.js +52 -0
  37. package/extension/dist/sidepanel.js.map +2 -2
  38. package/extension/dist/transparencypage.html +24 -0
  39. package/extension/dist/transparencypage.js +156 -0
  40. package/extension/dist/transparencypage.js.map +7 -0
  41. package/extension/manifest.json +5 -1
  42. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4837,6 +4837,169 @@ var sessionmemory = class {
4837
4837
  }
4838
4838
  return kept;
4839
4839
  }
4840
+ /**
4841
+ * Security part two persistence of the 1.1.62 family.
4842
+ * The protections for secrets, messages and money live here: the secretvault metadata with labels and scopes only and never values, scoped per profile workspace; the connectallow entries with their senders shipping empty by default; the ratelimit bucket state per origin and per session; the confirm gates with their resolution events and their human action provenance; the redactshot regions per origin and page template; the phishguard verdicts with their distance scores expiring past their freshness window; the permdiff records of each installed version; the safedefaults applications with their first seen origins; and the deferred command events waiting for their bucket reset.
4843
+ * The vault values never touch this seam: only metadata persists while the values stay behind the vault seam the background wires.
4844
+ */
4845
+ /** Replaces the secretvault metadata of the profile workspaces: labels, scopes, provenance and digests only, never values. */
4846
+ async setsecretvault(entries) {
4847
+ return this.adapter.set("secretvault", entries);
4848
+ }
4849
+ /** Returns the stored secretvault metadata, oldest record first; the values live behind the vault seam and never persist. */
4850
+ async getsecretvault() {
4851
+ return await this.adapter.get("secretvault") ?? [];
4852
+ }
4853
+ /** Adds one secretvault metadata record scoped to a profile workspace; a duplicate vault id keeps its first record. */
4854
+ async addsecret(entry) {
4855
+ const entries = await this.getsecretvault();
4856
+ if (entries.some((candidate) => candidate.vaultid === entry.vaultid)) return;
4857
+ await this.setsecretvault([...entries, entry]);
4858
+ }
4859
+ /** Removes one secretvault metadata record by its vault id; the background drops the value behind the seam in the same action. */
4860
+ async removesecret(vaultid) {
4861
+ await this.setsecretvault((await this.getsecretvault()).filter((entry) => entry.vaultid !== vaultid));
4862
+ }
4863
+ /** Stamps the last use of one secretvault record: the metadata notes when the vault last released its value while the value itself stays unrecorded. */
4864
+ async stampsecretuse(vaultid, at) {
4865
+ await this.setsecretvault((await this.getsecretvault()).map((entry) => entry.vaultid === vaultid ? { ...entry, lastusedat: at } : entry));
4866
+ }
4867
+ /** Replaces the connectallow entries of external senders; the list ships empty by default with user managed entries only. */
4868
+ async setconnectallow(entries) {
4869
+ return this.adapter.set("connectallow", entries);
4870
+ }
4871
+ /** Returns the stored connectallow entries, oldest add first. */
4872
+ async getconnectallow() {
4873
+ return await this.adapter.get("connectallow") ?? [];
4874
+ }
4875
+ /** Adds one connectallow entry for an external sender; a duplicate sender id keeps its first entry. */
4876
+ async addconnectallow(entry) {
4877
+ const entries = await this.getconnectallow();
4878
+ if (entries.some((candidate) => candidate.senderid === entry.senderid)) return;
4879
+ await this.setconnectallow([...entries, entry]);
4880
+ }
4881
+ /** Removes one connectallow entry by its sender id; the origincheck drops the sender again after the removal. */
4882
+ async removeconnectallow(senderid) {
4883
+ await this.setconnectallow((await this.getconnectallow()).filter((entry) => entry.senderid !== senderid));
4884
+ }
4885
+ /** Replaces the ratelimit bucket state per origin and per session: the user configured bounds and windows with their used counts. */
4886
+ async setratelimitbuckets(buckets) {
4887
+ return this.adapter.set("ratelimitbuckets", buckets);
4888
+ }
4889
+ /** Returns the stored ratelimit buckets per origin and per session. */
4890
+ async getratelimitbuckets() {
4891
+ return await this.adapter.get("ratelimitbuckets") ?? [];
4892
+ }
4893
+ /** Upserts one ratelimit bucket: a bucket of the same origin and session replaces its state while a new pair joins the list. */
4894
+ async saveratelimitbucket(bucket) {
4895
+ const buckets = await this.getratelimitbuckets();
4896
+ await this.setratelimitbuckets(buckets.some((candidate) => candidate.origin === bucket.origin && candidate.sessionid === bucket.sessionid) ? buckets.map((candidate) => candidate.origin === bucket.origin && candidate.sessionid === bucket.sessionid ? bucket : candidate) : [...buckets, bucket]);
4897
+ }
4898
+ /** Removes the ratelimit bucket of one origin and session; the origin runs without a bucket because the bounds stay user choices only. */
4899
+ async removeratelimitbucket(origin, sessionid) {
4900
+ await this.setratelimitbuckets((await this.getratelimitbuckets()).filter((bucket) => !(bucket.origin === origin && bucket.sessionid === sessionid)));
4901
+ }
4902
+ /** Replaces the confirm gates with their payloads and states; a resolved or refused gate stays terminal for the audit trail. */
4903
+ async setgates(gates) {
4904
+ return this.adapter.set("confirmgates", gates);
4905
+ }
4906
+ /** Returns the stored confirm gates, newest open first. */
4907
+ async getgates() {
4908
+ return await this.adapter.get("confirmgates") ?? [];
4909
+ }
4910
+ /** Upserts one confirm gate: a gate of the same step keeps its latest record because one gated step carries one live gate. */
4911
+ async savegate(gate) {
4912
+ const gates = await this.getgates();
4913
+ await this.setgates(gates.some((candidate) => candidate.stepid === gate.stepid && candidate.kind === gate.kind) ? gates.map((candidate) => candidate.stepid === gate.stepid && candidate.kind === gate.kind ? gate : candidate) : [gate, ...gates]);
4914
+ }
4915
+ /** Records one gate resolution event with its human action provenance; the resolution history stays visible for the audit trail. */
4916
+ async addgateresolution(resolution) {
4917
+ await this.adapter.set("gateresolutions", [resolution, ...await this.adapter.get("gateresolutions") ?? []].slice(0, 500));
4918
+ }
4919
+ /** Returns the recorded gate resolution events with their human action provenance, newest first. */
4920
+ async getgateresolutions() {
4921
+ return await this.adapter.get("gateresolutions") ?? [];
4922
+ }
4923
+ /** Replaces the redactshot regions per origin and page template. */
4924
+ async setredactregions(regions) {
4925
+ return this.adapter.set("redactregions", regions);
4926
+ }
4927
+ /** Returns the stored redactshot regions per origin and page template, oldest rule first. */
4928
+ async getredactregions() {
4929
+ return await this.adapter.get("redactregions") ?? [];
4930
+ }
4931
+ /** Adds one redactshot region, derived from a field shape or drawn by the user. */
4932
+ async addredactregion(region) {
4933
+ await this.setredactregions([...await this.getredactregions(), region]);
4934
+ }
4935
+ /** Removes one redactshot region by its id. */
4936
+ async removeredactregion(id) {
4937
+ await this.setredactregions((await this.getredactregions()).filter((region) => region.id !== id));
4938
+ }
4939
+ /** Records one phishguard verdict with its distance score; the records stay for the audit trail while the freshness window governs the live set. */
4940
+ async addphishverdict(verdict) {
4941
+ await this.adapter.set("phishverdicts", [verdict, ...(await this.adapter.get("phishverdicts") ?? []).filter((candidate) => candidate.origin !== verdict.origin)].slice(0, 500));
4942
+ }
4943
+ /** Returns the stored phishguard verdicts with their distance scores, newest first. */
4944
+ async getphishverdicts() {
4945
+ return await this.adapter.get("phishverdicts") ?? [];
4946
+ }
4947
+ /** Expires the phishguard verdicts past the user configured freshness window: the expired verdicts keep their records for the audit trail while the guard recomputes the next login step. */
4948
+ async expirephishverdicts(freshness, now) {
4949
+ const verdicts = await this.getphishverdicts();
4950
+ if (freshness === void 0) return verdicts;
4951
+ return verdicts.filter((verdict) => now - verdict.at < freshness);
4952
+ }
4953
+ /** Records one permdiff between two installed permission versions; the record of each installed update stays for the audit trail. */
4954
+ async addpermdiff(diff) {
4955
+ await this.adapter.set("permdiffs", [diff, ...await this.adapter.get("permdiffs") ?? []].slice(0, 500));
4956
+ }
4957
+ /** Returns the recorded permdiffs of each installed update, newest first. */
4958
+ async getpermdiffs() {
4959
+ return await this.adapter.get("permdiffs") ?? [];
4960
+ }
4961
+ /** Stores the last installed permission set the permdiff of the next update compares against. */
4962
+ async setlastpermissions(permissions, version) {
4963
+ await this.adapter.set("lastpermissions", { permissions, version });
4964
+ }
4965
+ /** Returns the last installed permission set with its version; an absent record returns undefined. */
4966
+ async getlastpermissions() {
4967
+ return this.adapter.get("lastpermissions");
4968
+ }
4969
+ /** Records one safedefaults application with its first seen origin; the first visit of an unknown origin stays visible. */
4970
+ async addsafedefaultapplication(application) {
4971
+ const applications = await this.adapter.get("safedefaults") ?? [];
4972
+ if (applications.some((candidate) => candidate.origin === application.origin)) return;
4973
+ await this.adapter.set("safedefaults", [...applications, application]);
4974
+ }
4975
+ /** Returns the recorded safedefaults applications with their first seen origins, oldest first. */
4976
+ async getsafedefaultapplications() {
4977
+ return await this.adapter.get("safedefaults") ?? [];
4978
+ }
4979
+ /** Records one deferred command event with the reset time it waits for. */
4980
+ async adddeferredevent(event) {
4981
+ await this.adapter.set("deferredevents", [event, ...await this.adapter.get("deferredevents") ?? []].slice(0, 500));
4982
+ }
4983
+ /** Returns the recorded deferred command events, newest first. */
4984
+ async getdeferredevents() {
4985
+ return await this.adapter.get("deferredevents") ?? [];
4986
+ }
4987
+ /** Serves the transparency data of the transparencypage in one read: every active grant with its origin, scope and boundary, every consent window ever granted with its expiry, the connectallow entries with their senders, the permdiff records of each installed update, the safedefaults applications and the secretvault metadata with labels and scopes only. */
4988
+ async gettransparencyview() {
4989
+ return {
4990
+ allowlist: await this.getautomationallowlist(),
4991
+ profiles: await this.getoriginprofiles(),
4992
+ windows: await this.getconsentwindows(),
4993
+ connectallow: await this.getconnectallow(),
4994
+ permdiffs: await this.getpermdiffs(),
4995
+ safedefaults: await this.getsafedefaultapplications(),
4996
+ vault: await this.getsecretvault(),
4997
+ gates: await this.getgates(),
4998
+ resolutions: await this.getgateresolutions(),
4999
+ deferred: await this.getdeferredevents(),
5000
+ phishverdicts: await this.getphishverdicts()
5001
+ };
5002
+ }
4840
5003
  };
4841
5004
  function mediakindof(record2) {
4842
5005
  if ("pages" in record2) return "pdf";
@@ -5477,6 +5640,87 @@ function tlsstateof(tls) {
5477
5640
  return { mode: tls.mode, certificaterequired: tls.mode === "required" || tls.certificatefingerprint !== void 0, verified: tls.verifiedat !== void 0 };
5478
5641
  }
5479
5642
 
5643
+ // confirmgates.ts
5644
+ function stepoptions(step) {
5645
+ if (!step.options) return {};
5646
+ try {
5647
+ const parsed = JSON.parse(step.options);
5648
+ return Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
5649
+ } catch {
5650
+ return {};
5651
+ }
5652
+ }
5653
+ function gatekindfor(classes) {
5654
+ if (classes.includes("payment")) return "confirmpay";
5655
+ if (classes.includes("delete")) return "confirmdelete";
5656
+ if (classes.includes("credential")) return "confirmcreds";
5657
+ return void 0;
5658
+ }
5659
+ function paypayload(input) {
5660
+ const payload = { payeeorigin: input.payeeorigin };
5661
+ if (input.amount !== void 0 && input.amount.trim() !== "") payload.amount = input.amount.trim();
5662
+ if (input.target !== void 0 && input.target.trim() !== "") payload.target = input.target.trim();
5663
+ return payload;
5664
+ }
5665
+ function deletepayload(input) {
5666
+ const payload = { scope: input.scope, irreversibility: input.irreversibility };
5667
+ if (input.target !== void 0 && input.target.trim() !== "") payload.target = input.target.trim();
5668
+ return payload;
5669
+ }
5670
+ function credspayload(label) {
5671
+ if (label.trim() === "") throw new Error("The confirmcreds gate names its credential label; the value never appears.");
5672
+ return { label: label.trim() };
5673
+ }
5674
+ function opengate(input) {
5675
+ if (input.stepid.trim() === "" || input.runid.trim() === "" || input.origin.trim() === "") throw new Error("The confirm gate needs its step, run and origin.");
5676
+ if (Object.keys(input.payload).length === 0) throw new Error("The confirm gate carries the payload the human reviews.");
5677
+ return { gateid: input.gateid ?? randomid(), kind: input.kind, stepid: input.stepid, runid: input.runid, origin: input.origin, payload: { ...input.payload }, state: "open", openedat: input.now };
5678
+ }
5679
+ function gatestateof(gates, stepid) {
5680
+ const gate = [...gates].reverse().find((candidate) => candidate.stepid === stepid);
5681
+ if (gate === void 0) return { state: "none" };
5682
+ return { state: gate.state, gate };
5683
+ }
5684
+ function resolvegate(input) {
5685
+ if (input.actor.trim() === "") throw new Error("The gate resolution names its acting user; only a human resolves a gate.");
5686
+ const gate = input.gates.find((candidate) => candidate.gateid === input.gateid);
5687
+ if (gate === void 0) return { gates: input.gates };
5688
+ if (gate.state !== "open") return { gates: input.gates };
5689
+ const resolution = { gateid: gate.gateid, kind: gate.kind, stepid: gate.stepid, decision: input.decision, actor: input.actor, at: input.now };
5690
+ return { gates: input.gates.map((candidate) => candidate.gateid === input.gateid ? { ...candidate, state: input.decision, resolvedat: input.now, actor: input.actor } : candidate), resolution };
5691
+ }
5692
+ function nobatchresolution(gateids) {
5693
+ if (gateids.length > 1) return { allowed: false, reason: `One human action resolves exactly one gate; the batch of ${gateids.length} gates refuses in full because no batch approval exists.` };
5694
+ if (gateids.length === 0) return { allowed: false, reason: "A gate resolution names its single gate." };
5695
+ return { allowed: true, reason: "The resolution names exactly one gate; the distinct human action resolves it alone." };
5696
+ }
5697
+ function gateprompttext(gate) {
5698
+ if (gate.kind === "confirmpay") {
5699
+ const amount = gate.payload.amount !== void 0 ? `the amount ${gate.payload.amount}` : "an amount the step options name";
5700
+ const target = gate.payload.target !== void 0 ? ` on ${gate.payload.target}` : "";
5701
+ return `Approve the payment of ${amount} to ${gate.payload.payeeorigin}${target}? The step dispatches only after this distinct human action.`;
5702
+ }
5703
+ if (gate.kind === "confirmdelete") {
5704
+ const target = gate.payload.target !== void 0 ? ` on ${gate.payload.target}` : "";
5705
+ return `Approve the destructive delete${target} scoped to ${gate.payload.scope}? ${gate.payload.irreversibility} The step dispatches only after this distinct human action.`;
5706
+ }
5707
+ return `Approve the use of the credential ${gate.payload.label} on ${gate.origin}? The value stays behind the vault; the label is everything this prompt shows.`;
5708
+ }
5709
+ function gateforstep(input) {
5710
+ const kind = gatekindfor(input.classes);
5711
+ if (kind === void 0) return void 0;
5712
+ const options = stepoptions(input.step);
5713
+ if (kind === "confirmpay") {
5714
+ const amount = typeof options.amount === "string" ? options.amount : typeof options.value === "string" ? options.value : void 0;
5715
+ return opengate({ kind, stepid: input.step.id, runid: input.runid, origin: input.origin, payload: paypayload({ ...amount !== void 0 && amount !== "" ? { amount } : {}, payeeorigin: String(options.payeeorigin ?? input.origin), ...input.step.target !== void 0 && input.step.target !== "" ? { target: input.step.target } : {} }), now: input.now });
5716
+ }
5717
+ if (kind === "confirmdelete") {
5718
+ return opengate({ kind, stepid: input.step.id, runid: input.runid, origin: input.origin, payload: deletepayload({ ...input.step.target !== void 0 && input.step.target !== "" ? { target: input.step.target } : {}, scope: String(options.scope ?? input.origin), irreversibility: String(options.irreversibility ?? "A destructive delete destroys state the page cannot restore.") }), now: input.now });
5719
+ }
5720
+ if (input.credentiallabel === void 0 || input.credentiallabel.trim() === "") return void 0;
5721
+ return opengate({ kind, stepid: input.step.id, runid: input.runid, origin: input.origin, payload: credspayload(input.credentiallabel), now: input.now });
5722
+ }
5723
+
5480
5724
  // coordination.ts
5481
5725
  function lockkey(origin, selector) {
5482
5726
  return `${origin}|${selector}`;
@@ -6039,6 +6283,88 @@ async function callgraphql(input) {
6039
6283
  }
6040
6284
  }
6041
6285
 
6286
+ // inboundguard.ts
6287
+ function shapeof(value) {
6288
+ if (typeof value === "string") return "string";
6289
+ if (typeof value === "number") return "number";
6290
+ if (typeof value === "boolean") return "boolean";
6291
+ if (Array.isArray(value)) return "array";
6292
+ return "object";
6293
+ }
6294
+ function schemacheck(input) {
6295
+ const errors = [];
6296
+ for (const [field, value] of Object.entries(input.command)) {
6297
+ const expected = input.schema[field];
6298
+ if (expected === void 0) {
6299
+ errors.push({ path: field, expected: "absent", found: shapeof(value), reason: `The ${field} field sits absent from the declared grammar of the command; schemastrict refuses unknown fields before dispatch.` });
6300
+ continue;
6301
+ }
6302
+ if (expected === "absent") {
6303
+ errors.push({ path: field, expected: "absent", found: shapeof(value), reason: `The ${field} field carries no value under the declared grammar; schemastrict refuses it before dispatch.` });
6304
+ continue;
6305
+ }
6306
+ if (shapeof(value) !== expected) errors.push({ path: field, expected, found: shapeof(value), reason: `The ${field} field expects a ${expected} while the command carries a ${shapeof(value)}; schemastrict refuses the shape mismatch before dispatch.` });
6307
+ }
6308
+ for (const field of input.required ?? []) {
6309
+ if (input.command[field] === void 0) errors.push({ path: field, expected: input.schema[field] ?? "string", found: "absent", reason: `The ${field} field is required by the declared grammar and the command carries no value; schemastrict refuses the incomplete command before dispatch.` });
6310
+ }
6311
+ return { valid: errors.length === 0, errors };
6312
+ }
6313
+ function envelopecheck(input) {
6314
+ const kind = input.command.kind;
6315
+ if (typeof kind !== "string" || kind.trim() === "") return { valid: false, errors: [{ path: "kind", expected: "string", found: shapeof(kind), reason: "Every inbound command names its kind as a non-empty string; a kindless command never dispatches." }] };
6316
+ if (!input.knownkinds.includes(kind)) return { valid: false, errors: [{ path: "kind", expected: `one of ${input.knownkinds.length} declared command kinds`, found: kind, reason: `The ${kind} command kind sits absent from the dispatch registry; schemastrict refuses unknown commands before dispatch.` }] };
6317
+ return { valid: true, errors: [] };
6318
+ }
6319
+ function origincheckof(input) {
6320
+ const sender = input.senderid ?? "an unknown sender";
6321
+ const origin = input.senderorigin ?? "";
6322
+ if (input.senderid === input.extensionid) return { accepted: true, sender, origin, reason: "The sender is this extension itself; the internal surface accepts." };
6323
+ if (input.senderid !== void 0 && input.connectallow.some((entry) => entry.senderid === input.senderid && (entry.origin === void 0 || entry.origin === origin))) {
6324
+ return { accepted: true, sender, origin, reason: `The sender ${sender} sits in the connectallow list the user manages${origin !== "" ? ` for ${origin}` : ""}; the message accepts.` };
6325
+ }
6326
+ if (input.senderid === void 0) return { accepted: false, sender, origin, reason: "The message carries no sender identity; the guard drops it before any handler runs." };
6327
+ return { accepted: false, sender, origin, reason: `The sender ${sender} sits absent from the connectallow list; the guard drops the message without handler execution.` };
6328
+ }
6329
+ function portaccept(input) {
6330
+ const verdict = origincheckof(input);
6331
+ if (!verdict.accepted) return { ...verdict, reason: `The port ${input.portname} closes at its handshake: ${verdict.reason}` };
6332
+ return { ...verdict, reason: `The port ${input.portname} accepted its handshake: ${verdict.reason}` };
6333
+ }
6334
+ function connectallowentryof(input) {
6335
+ if (input.senderid.trim() === "") throw new Error("The connectallow entry needs its sender id.");
6336
+ if (input.displayname.trim() === "") throw new Error("The connectallow entry needs its display name.");
6337
+ return { senderid: input.senderid.trim(), displayname: input.displayname.trim(), ...input.origin !== void 0 && input.origin.trim() !== "" ? { origin: input.origin.trim() } : {}, addedat: input.now };
6338
+ }
6339
+ var emptyconnectallow = [];
6340
+ function bucketboundsvalid(limit, window) {
6341
+ if (!Number.isFinite(limit) || limit <= 0) return { valid: false, reason: "The ratelimit bucket limit stays a positive user value; no hidden ceiling exists." };
6342
+ if (!Number.isFinite(window) || window <= 0) return { valid: false, reason: "The ratelimit bucket window stays a positive user value in milliseconds; the window reset stays the user's choice." };
6343
+ return { valid: true, reason: `The bucket bound of ${limit} commands per ${window} milliseconds stays the user configured choice with no hidden ceiling.` };
6344
+ }
6345
+ function bucketof(input) {
6346
+ const bounds = bucketboundsvalid(input.limit, input.window);
6347
+ if (!bounds.valid) throw new Error(bounds.reason);
6348
+ return { origin: input.origin, sessionid: input.sessionid, limit: input.limit, window: input.window, used: 0, windowstartedat: input.now, resetsat: input.now + input.window };
6349
+ }
6350
+ function bucketconsume(input) {
6351
+ if (input.now >= input.bucket.resetsat) {
6352
+ const fresh = { ...input.bucket, used: 0, windowstartedat: input.now, resetsat: input.now + input.bucket.window };
6353
+ return { allowed: true, deferred: false, bucket: { ...fresh, used: 1 }, resetsat: fresh.resetsat, reason: `The bucket window of ${input.bucket.origin} reset and the command consumes the first slot of ${fresh.limit}.` };
6354
+ }
6355
+ if (input.bucket.used < input.bucket.limit) {
6356
+ return { allowed: true, deferred: false, bucket: { ...input.bucket, used: input.bucket.used + 1 }, resetsat: input.bucket.resetsat, reason: `The command consumes slot ${input.bucket.used + 1} of ${input.bucket.limit} in the bucket of ${input.bucket.origin}.` };
6357
+ }
6358
+ return { allowed: false, deferred: true, bucket: input.bucket, resetsat: input.bucket.resetsat, reason: `The bucket of ${input.bucket.origin} holds its ${input.bucket.limit} command bound; the command defers until the window resets at ${input.bucket.resetsat}.` };
6359
+ }
6360
+ function deferredeventof(input) {
6361
+ if (input.stepid.trim() === "" || input.kind.trim() === "") throw new Error("The deferred event needs its step and kind.");
6362
+ return { id: input.id ?? randomid(), stepid: input.stepid, kind: input.kind, origin: input.origin, reason: input.reason, resetsat: input.resetsat, at: input.now };
6363
+ }
6364
+ function deferredready(deferred, now) {
6365
+ return now >= deferred.resetsat;
6366
+ }
6367
+
6042
6368
  // originpolicy.ts
6043
6369
  var denydefaultposture = "denydefault";
6044
6370
  function exactorigin(origin, entry) {
@@ -6076,7 +6402,7 @@ function profilegrade(input) {
6076
6402
  if (input.profile.grants.includes(input.kind)) return { allowed: true, consult: true, reason: `The origin profile of ${input.profile.origin} grants the ${input.kind} kind the user reviewed.` };
6077
6403
  return { allowed: true, consult: true, reason: `The origin profile of ${input.profile.origin} carries no ${input.kind} decision, so the fresh class consent gate alone routes the sensitive step.` };
6078
6404
  }
6079
- function stepoptions(step) {
6405
+ function stepoptions2(step) {
6080
6406
  if (!step.options) return {};
6081
6407
  try {
6082
6408
  const parsed = JSON.parse(step.options);
@@ -6091,7 +6417,7 @@ var deletekinds = /* @__PURE__ */ new Set(["discardtab", "closepattern", "clearc
6091
6417
  var publishkinds = /* @__PURE__ */ new Set(["postform", "postfiles", "sendmessage", "submitform", "submitsearch", "writeclipboard"]);
6092
6418
  var defaultsensitivekinds = /* @__PURE__ */ new Set(["attachfile", "uploadfile", "uploadfiles", "downloadfile", "downloadimages", "batchdownload", "pausedownload", "resumedownload", "quarantinedownload", "evaluate"]);
6093
6419
  function sensitiveclassesof(step) {
6094
- const options = stepoptions(step);
6420
+ const options = stepoptions2(step);
6095
6421
  const fields = Array.isArray(options.fields) ? options.fields.filter((item) => Boolean(item) && typeof item === "object") : [];
6096
6422
  const names = [...fields.map((field) => typeof field.name === "string" ? field.name : ""), typeof options.field === "string" ? options.field : "", typeof options.target === "string" ? options.target : ""].map((name) => name.toLowerCase());
6097
6423
  const carries = (shape) => names.some((name) => name.includes(shape));
@@ -6176,6 +6502,18 @@ function profilesummary(profile) {
6176
6502
  if (profile === void 0) return "No origin profile exists for this origin yet; sensitive steps route through their fresh consent prompts.";
6177
6503
  return `The origin profile of ${profile.origin} grants ${profile.grants.length} kind${profile.grants.length === 1 ? "" : "s"} and denies ${profile.denials.length} kind${profile.denials.length === 1 ? "" : "s"} the user reviewed.`;
6178
6504
  }
6505
+ var safedefaultreadkinds = /* @__PURE__ */ new Set(["observe", "readhtml", "readtext", "readlinks", "readtable", "readforms", "readvisible", "readselection", "readmeta", "readlang", "readoutline", "readstyle", "readimages", "readertree"]);
6506
+ function safedefaultprofile(input) {
6507
+ if (input.origin.trim() === "") throw new Error("The safedefaults profile needs its exact origin.");
6508
+ const denials = /* @__PURE__ */ new Set([...paymentkinds, ...credentialkinds, ...deletekinds, ...publishkinds, ...defaultsensitivekinds]);
6509
+ return { profileid: input.profileid ?? randomid(), origin: input.origin.trim(), grants: [...safedefaultreadkinds], denials: [...denials], createdat: input.now, updatedat: input.now };
6510
+ }
6511
+ function safedefaultreadkind(kind) {
6512
+ return safedefaultreadkinds.has(kind);
6513
+ }
6514
+ function safedefaultnotice(origin) {
6515
+ return `The safedefaults posture profiles ${origin} on its first visit: reads only, every sensitive class denied; open the originprofile editor to widen the profile.`;
6516
+ }
6179
6517
 
6180
6518
  // socketbus.ts
6181
6519
  var socketkinds = ["opensocket", "sendmessage", "waitmessage", "subscribesse", "longpoll"];
@@ -7474,6 +7812,87 @@ function consolediff(input) {
7474
7812
  return { base: input.baseid, target: input.targetid, lines, added: added.length, removed: removed.length, repeated: repeated.length, at: input.now };
7475
7813
  }
7476
7814
 
7815
+ // phishguard.ts
7816
+ function stepoptions3(step) {
7817
+ if (!step.options) return {};
7818
+ try {
7819
+ const parsed = JSON.parse(step.options);
7820
+ return Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
7821
+ } catch {
7822
+ return {};
7823
+ }
7824
+ }
7825
+ function credentialstep(step) {
7826
+ const credentialkinds2 = /* @__PURE__ */ new Set(["consentpassword", "saveapikey", "handleauth", "authflow", "fillcard", "fillcode"]);
7827
+ if (credentialkinds2.has(step.kind)) return true;
7828
+ const options = stepoptions3(step);
7829
+ const fields = Array.isArray(options.fields) ? options.fields.filter((item) => Boolean(item) && typeof item === "object") : [];
7830
+ const names = [...fields.map((field) => typeof field.name === "string" ? field.name : ""), typeof options.field === "string" ? options.field : "", step.target ?? ""].map((name) => name.toLowerCase());
7831
+ return names.some((name) => name.includes("password") || name.includes("passwd") || name.includes("passphrase") || name.includes("token") || name.includes("secret") || name.includes("apikey"));
7832
+ }
7833
+ function originlabels(origin) {
7834
+ const host = origin.trim().replace(/^[a-z][a-z0-9+.-]*:\/\//i, "").split("/")[0] ?? "";
7835
+ return host.split(".").filter((label) => label !== "").reverse();
7836
+ }
7837
+ function labeldistance(one, two) {
7838
+ const rows = one.length + 1;
7839
+ const columns = two.length + 1;
7840
+ let previous = Array.from({ length: columns }, (_, index) => index);
7841
+ for (let row = 1; row < rows; row += 1) {
7842
+ const current = [row, ...Array.from({ length: columns - 1 }, () => 0)];
7843
+ for (let column = 1; column < columns; column += 1) {
7844
+ const substitution = (previous[column - 1] ?? 0) + (one[row - 1] === two[column - 1] ? 0 : 1);
7845
+ current[column] = Math.min((previous[column] ?? 0) + 1, (current[column - 1] ?? 0) + 1, substitution);
7846
+ }
7847
+ previous = current;
7848
+ }
7849
+ return previous[columns - 1] ?? Math.max(one.length, two.length);
7850
+ }
7851
+ function lookalikedistance(one, two) {
7852
+ if (one.trim() === "" || two.trim() === "") return 1;
7853
+ if (one === two) return 0;
7854
+ const first = originlabels(one);
7855
+ const second = originlabels(two);
7856
+ const edits = labeldistance(first, second);
7857
+ const longest = Math.max(first.length, second.length);
7858
+ if (longest === 0) return 1;
7859
+ const distance = edits / longest;
7860
+ return Math.min(1, Math.max(0, distance));
7861
+ }
7862
+ function phishthresholdvalid(threshold) {
7863
+ if (!Number.isFinite(threshold) || threshold <= 0 || threshold >= 1) return { valid: false, reason: "The phishguard threshold stays a user choice between zero and one; the lookalike line never defaults." };
7864
+ return { valid: true, reason: `The lookalike threshold ${threshold} stays the user configured line a login origin crosses at its own risk.` };
7865
+ }
7866
+ function phishverdictof(input) {
7867
+ const threshold = phishthresholdvalid(input.threshold);
7868
+ if (!threshold.valid) throw new Error(threshold.reason);
7869
+ if (input.granted.includes(input.origin)) {
7870
+ return { origin: input.origin, distance: 0, threshold: input.threshold, blocked: false, reason: `The login origin ${input.origin} sits among the granted origins; no lookalike watch applies.`, at: input.now };
7871
+ }
7872
+ let matchedorigin;
7873
+ let distance = 1;
7874
+ for (const granted of input.granted) {
7875
+ const candidate = lookalikedistance(input.origin, granted);
7876
+ if (candidate < distance) {
7877
+ distance = candidate;
7878
+ matchedorigin = granted;
7879
+ }
7880
+ }
7881
+ if (matchedorigin !== void 0 && distance <= input.threshold) {
7882
+ return { origin: input.origin, matchedorigin, distance, threshold: input.threshold, blocked: true, reason: `The login origin ${input.origin} sits ${distance} away from the granted origin ${matchedorigin} and crosses the user threshold ${input.threshold}; the credential step blocks and the deny event names ${matchedorigin}.`, at: input.now };
7883
+ }
7884
+ return { origin: input.origin, ...matchedorigin !== void 0 ? { matchedorigin } : {}, distance, threshold: input.threshold, blocked: false, reason: matchedorigin !== void 0 ? `The login origin ${input.origin} sits ${distance} away from its closest granted origin ${matchedorigin} and stays under the user threshold ${input.threshold}.` : `The login origin ${input.origin} carries no granted origin to resemble; the watch records the first visit.`, at: input.now };
7885
+ }
7886
+ function verdictfresh(verdict, now, freshness) {
7887
+ if (freshness === void 0) return true;
7888
+ return now - verdict.at < freshness;
7889
+ }
7890
+ function phishnotetext(verdict) {
7891
+ if (verdict.blocked) return verdict.reason;
7892
+ if (verdict.matchedorigin !== void 0) return `The login origin ${verdict.origin} sits ${verdict.distance} from the granted origin ${verdict.matchedorigin}, under the user threshold ${verdict.threshold}.`;
7893
+ return `The login origin ${verdict.origin} has no granted lookalike under the user threshold ${verdict.threshold}.`;
7894
+ }
7895
+
7477
7896
  // policy.ts
7478
7897
  var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps", "emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "restoresession", "exportsessions", "importsessions", "runworkflow", "visitrule", "urlrule", "menurule", "keyrule", "buttonrule", "cronrule", "intervalrule", "urllistrule", "webhookrule", "eventrule"]);
7479
7898
  var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction", "capturebodies", "setbreakpoint", "stepcode", "watchexpr", "loop", "repeatuntil", "whileloop", "foreach", "parallel", "trycatch"]);
@@ -10599,6 +11018,83 @@ function sensitivepipelingate(input) {
10599
11018
  if (!consentverdict.allowed) return { allowed: false, reason: `${classification.reason} ${consentverdict.reason}` };
10600
11019
  return { allowed: true, reason: `${classification.reason} ${consentverdict.reason}` };
10601
11020
  }
11021
+ function schemaguardgate(input) {
11022
+ if (input.errors.length === 0) return { allowed: true, reason: "The inbound command matches its declared schemastrict grammar field by field." };
11023
+ const first = input.errors[0];
11024
+ return { allowed: false, reason: `${input.errors.length} schema error${input.errors.length === 1 ? "" : "s"} refuse the command before dispatch: ${input.errors.map((error) => error.reason).join(" ")}${first !== void 0 ? ` The first error sits at ${first.path} expecting ${first.expected}.` : ""}` };
11025
+ }
11026
+ function origincheckgate(input) {
11027
+ if (!input.verdict.accepted) return { allowed: false, reason: input.verdict.reason };
11028
+ return { allowed: true, reason: input.verdict.reason };
11029
+ }
11030
+ function connectallowgate(input) {
11031
+ const verdict = origincheckof(input);
11032
+ if (!verdict.accepted) return { allowed: false, reason: verdict.reason };
11033
+ return { allowed: true, reason: verdict.reason };
11034
+ }
11035
+ function ratelimitboundsvalid(limit, window) {
11036
+ const bounds = bucketboundsvalid(limit, window);
11037
+ if (!bounds.valid) return { allowed: false, reason: bounds.reason };
11038
+ return { allowed: true, reason: bounds.reason };
11039
+ }
11040
+ function ratelimitgate(input) {
11041
+ if (input.bucket === void 0) return { allowed: true, reason: "No ratelimit bucket covers the origin of the command; the bounds stay user configured choices only." };
11042
+ if (input.now >= input.bucket.resetsat) return { allowed: true, reason: `The bucket window of ${input.bucket.origin} reset at ${input.bucket.resetsat}; the command consumes the first slot of its fresh window.` };
11043
+ if (input.bucket.used < input.bucket.limit) return { allowed: true, reason: `The command consumes slot ${input.bucket.used + 1} of ${input.bucket.limit} in the bucket of ${input.bucket.origin}.` };
11044
+ return { allowed: false, reason: `The bucket of ${input.bucket.origin} holds its ${input.bucket.limit} command bound; the command defers until the window resets at ${input.bucket.resetsat}.` };
11045
+ }
11046
+ function confirmpaygate(input) {
11047
+ const kind = gatekindfor(input.classes);
11048
+ if (kind !== "confirmpay") return { allowed: true, reason: "The step carries no payment class and needs no confirmpay gate." };
11049
+ if (input.state === "resolved") return { allowed: true, reason: "The human resolved the confirmpay gate of the payment step; the step dispatches with its reviewed amount, payee origin and target." };
11050
+ if (input.state === "refused") return { allowed: false, reason: "The human refused the confirmpay gate of the payment step; the payment never dispatches." };
11051
+ if (input.state === "open") return { allowed: false, reason: "The confirmpay gate of the payment step stays open with the amount, the payee origin and the target element; the executor pauses until the human resolves it and no timeout ever resolves a gate." };
11052
+ return { allowed: false, reason: "The payment step opens its confirmpay gate with the amount, the payee origin and the target element; the executor pauses until one distinct human action resolves it." };
11053
+ }
11054
+ function confirmdeletegate(input) {
11055
+ const kind = gatekindfor(input.classes);
11056
+ if (kind !== "confirmdelete") return { allowed: true, reason: "The step carries no delete class and needs no confirmdelete gate." };
11057
+ if (input.state === "resolved") return { allowed: true, reason: "The human resolved the confirmdelete gate of the destructive step; the step dispatches with its reviewed target, scope and irreversibility." };
11058
+ if (input.state === "refused") return { allowed: false, reason: "The human refused the confirmdelete gate of the destructive step; the deletion never dispatches." };
11059
+ if (input.state === "open") return { allowed: false, reason: "The confirmdelete gate of the destructive step stays open with the target, the scope and the irreversibility; the executor pauses until the human resolves it and no timeout ever resolves a gate." };
11060
+ return { allowed: false, reason: "The destructive step opens its confirmdelete gate with the target, the scope and the irreversibility; the executor pauses until one distinct human action resolves it." };
11061
+ }
11062
+ function confirmcredsgate(input) {
11063
+ const kind = gatekindfor(input.classes);
11064
+ if (kind !== "confirmcreds") return { allowed: true, reason: "The step carries no credential class and needs no confirmcreds gate." };
11065
+ if (input.state === "resolved") return { allowed: true, reason: "The human resolved the confirmcreds gate of the credential step; the step reads its value from the vault at the last possible moment and no log records it." };
11066
+ if (input.state === "refused") return { allowed: false, reason: "The human refused the confirmcreds gate of the credential step; the credential never dispatches." };
11067
+ if (input.state === "open") return { allowed: false, reason: "The confirmcreds gate of the credential step stays open with its credential label only; the executor pauses until the human resolves it and no timeout ever resolves a gate." };
11068
+ return { allowed: false, reason: "The credential step opens its confirmcreds gate with its credential label only; the executor pauses until one distinct human action resolves it." };
11069
+ }
11070
+ function gatebatchgate(input) {
11071
+ if (input.gateids.length === 0) return { allowed: false, reason: "A gate resolution names its single gate." };
11072
+ if (input.gateids.length > 1) return { allowed: false, reason: `One human action resolves exactly one gate; the batch of ${input.gateids.length} gates refuses in full because no batch approval exists.` };
11073
+ return { allowed: true, reason: "The resolution names exactly one gate; the distinct human action resolves it alone." };
11074
+ }
11075
+ function phishthresholdgate(threshold) {
11076
+ const verdict = phishthresholdvalid(threshold);
11077
+ if (!verdict.valid) return { allowed: false, reason: verdict.reason };
11078
+ return { allowed: true, reason: verdict.reason };
11079
+ }
11080
+ function phishguardgate(input) {
11081
+ if (input.verdict.blocked) return { allowed: false, reason: input.verdict.reason };
11082
+ return { allowed: true, reason: input.verdict.reason };
11083
+ }
11084
+ function safedefaultsgate(input) {
11085
+ if (input.profile !== void 0) return { allowed: true, reason: `The origin profile of ${input.profile.origin} exists; the safedefaults posture stays out of the decision.` };
11086
+ if (!input.sensitive) return { allowed: true, reason: "The non-sensitive step rides the reads only baseline of the safedefaults posture; the first visit grants reads alone." };
11087
+ return { allowed: false, reason: `No origin profile exists and the safedefaults posture denies the sensitive ${input.classes.length > 0 ? input.classes.join(" and ") : "by default"} step; open the originprofile editor to widen the profile the user controls.` };
11088
+ }
11089
+ function vaultsecretgate(input) {
11090
+ if (input.leaks.length > 0) return { allowed: false, reason: `The plan carries ${input.leaks.length} plaintext secret value${input.leaks.length === 1 ? "" : "s"} that digest to vault records; secrets never ride step options, variables or plan texts, only the vault holds them.` };
11091
+ if (input.carries) return { allowed: false, reason: "The step types a raw value into a masked field shape; credential steps read their value from the vault at the last possible moment and never carry it in the options." };
11092
+ return { allowed: true, reason: "The step and the plan carry no secret outside the vault; the values stay behind the seam." };
11093
+ }
11094
+ function untrustedrendergate(input) {
11095
+ if (input.environment === "sandboxframe") return { allowed: true, reason: "The extracted markup renders inside the sandboxframe under its nonce with scripts and handlers stripped; the untrusted content never reenters the page context." };
11096
+ return { allowed: false, reason: `The extracted markup grades untrusted and refuses to render inside the ${input.environment}; every untrusted render routes through the sandboxframe.` };
11097
+ }
10602
11098
 
10603
11099
  // llm.ts
10604
11100
  var defaultrefusalmarkers = ["i cannot", "i can't", "i'm unable", "refusal:", "cannot comply"];
@@ -10959,7 +11455,7 @@ function budgetcheck(input) {
10959
11455
  }
10960
11456
 
10961
11457
  // version.ts
10962
- var packageversion = "1.1.61";
11458
+ var packageversion = "1.1.62";
10963
11459
 
10964
11460
  // types.ts
10965
11461
  var protocolversion = packageversion;
@@ -11883,6 +12379,67 @@ function removetemplate(templates, name) {
11883
12379
  return templates.filter((template) => template.name !== name);
11884
12380
  }
11885
12381
 
12382
+ // redactshots.ts
12383
+ function regionof(input) {
12384
+ if (input.origin.trim() === "" || input.template.trim() === "") throw new Error("The redact region needs its origin and its page template.");
12385
+ for (const value of [input.x, input.y, input.width, input.height]) {
12386
+ if (!Number.isFinite(value) || value < 0) throw new Error("The redact region needs finite, non-negative geometry in css pixels.");
12387
+ }
12388
+ if (input.width <= 0 || input.height <= 0) throw new Error("The redact region needs a positive width and height so the mask covers a real area.");
12389
+ if (input.reason.trim() === "") throw new Error("The redact region names its reason in plain language.");
12390
+ return { id: input.id ?? randomid(), origin: input.origin.trim(), template: input.template.trim(), x: input.x, y: input.y, width: input.width, height: input.height, reason: input.reason.trim(), source: input.source, createdat: input.now };
12391
+ }
12392
+ function regionvalid(region) {
12393
+ return Number.isFinite(region.x) && Number.isFinite(region.y) && Number.isFinite(region.width) && Number.isFinite(region.height) && region.width > 0 && region.height > 0;
12394
+ }
12395
+ function regionsfor(regions, origin, template) {
12396
+ return regions.filter((region) => region.origin === origin && region.template === template);
12397
+ }
12398
+ function fieldshaperegions(input) {
12399
+ const regions = [];
12400
+ for (const field of input.fields) {
12401
+ if (!maskingfield(field.name, [])) continue;
12402
+ regions.push(regionof({ origin: input.origin, template: input.template, x: field.rect.x, y: field.rect.y, width: field.rect.width, height: field.rect.height, reason: `The ${field.name} field carries a sensitive field shape the recognizer masks.`, source: "fieldshape", now: input.now }));
12403
+ }
12404
+ return regions;
12405
+ }
12406
+ function mergeregions(existing, added) {
12407
+ const merged = [...existing];
12408
+ for (const region of added) {
12409
+ if (merged.some((candidate) => candidate.origin === region.origin && candidate.template === region.template && candidate.x === region.x && candidate.y === region.y && candidate.width === region.width && candidate.height === region.height)) continue;
12410
+ merged.push(region);
12411
+ }
12412
+ return merged;
12413
+ }
12414
+ function capturesurfaceof(kind) {
12415
+ if (kind === "element" || kind === "elementshot") return "element";
12416
+ if (kind === "stitched" || kind === "fullpage" || kind === "shotfullpage" || kind === "stitch" || kind === "contactsheet" || kind === "timelapse" || kind === "recordscreen") return "stitched";
12417
+ return "viewport";
12418
+ }
12419
+ function templateof(step) {
12420
+ if (step.options) {
12421
+ try {
12422
+ const parsed = JSON.parse(step.options);
12423
+ if (Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed)) {
12424
+ const template = parsed.template;
12425
+ if (typeof template === "string" && template.trim() !== "") return template.trim();
12426
+ }
12427
+ } catch {
12428
+ }
12429
+ }
12430
+ return step.kind;
12431
+ }
12432
+ function redactedshot(record2, regions) {
12433
+ if (regions.length === 0) return record2;
12434
+ return { ...record2, redacted: true, redactedregions: regions.length };
12435
+ }
12436
+ function redactionsummary(regions) {
12437
+ if (regions.length === 0) return "No redact region covered the capture; the stored bytes carry everything the surface saw.";
12438
+ const sources = { fieldshape: 0, userdrawn: 0 };
12439
+ for (const region of regions) sources[region.source] += 1;
12440
+ return `${regions.length} redact region${regions.length === 1 ? "" : "s"} covered the capture before storage: ${sources.fieldshape} derived from sensitive field shapes and ${sources.userdrawn} drawn by the user (${regions.map((region) => region.reason).join("; ")}).`;
12441
+ }
12442
+
11886
12443
  // sandboxframe.ts
11887
12444
  function stripscripts(markup) {
11888
12445
  return markup.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<script\b[^>]*\/>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*[^\s>]+/gi, "").replace(/javascript:/gi, "").trim();
@@ -11921,6 +12478,82 @@ function renderprovenance(render) {
11921
12478
  return { origin: render.sourceorigin, stepid: render.stepid, environment: "sandboxframe" };
11922
12479
  }
11923
12480
 
12481
+ // secretvault.ts
12482
+ var vaultdigestprefix = "sha256:";
12483
+ async function vaultdigestof(value) {
12484
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
12485
+ return vaultdigestprefix + [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
12486
+ }
12487
+ function vaultentryof(input) {
12488
+ if (input.label.trim() === "") throw new Error("The vault record needs its label; the surfaces show the label only.");
12489
+ if (input.scope.trim() === "") throw new Error("The vault record needs its exact origin scope; a secret never rides every origin.");
12490
+ if (!input.digest.startsWith(vaultdigestprefix)) throw new Error("The vault record carries its sha-256 digest, never its value.");
12491
+ return { vaultid: input.vaultid ?? randomid(), label: input.label.trim(), scope: input.scope.trim(), profileid: input.profileid, provenance: input.provenance, algorithm: "sha-256", digest: input.digest, createdat: input.now };
12492
+ }
12493
+ function inmemoryvault() {
12494
+ const values = /* @__PURE__ */ new Map();
12495
+ return {
12496
+ put: async (vaultid, value) => {
12497
+ values.set(vaultid, value);
12498
+ },
12499
+ fetch: async (vaultid) => values.get(vaultid),
12500
+ drop: async (vaultid) => {
12501
+ values.delete(vaultid);
12502
+ }
12503
+ };
12504
+ }
12505
+ async function vaultstore(input) {
12506
+ if (input.value === "") throw new Error("The vault stores a secret value the user supplied; an empty value stores nothing.");
12507
+ const entry = vaultentryof({ label: input.label, scope: input.scope, profileid: input.profileid, provenance: input.provenance, digest: await vaultdigestof(input.value), now: input.now });
12508
+ await input.seam.put(entry.vaultid, input.value);
12509
+ return entry;
12510
+ }
12511
+ async function vaultvaluefor(input) {
12512
+ const value = await input.seam.fetch(input.entry.vaultid);
12513
+ if (value === void 0) return { ok: false, reason: `The vault holds no value behind the label ${input.entry.label}; add the secret again.` };
12514
+ return { ok: true, value, reason: `The vault released the value behind the label ${input.entry.label} at the last possible moment; the value reaches the credential field only and no log records it.` };
12515
+ }
12516
+ async function vaultdelete(input) {
12517
+ await input.seam.drop(input.entry.vaultid);
12518
+ return { dropped: true, label: input.entry.label, reason: `The vault dropped the secret ${input.entry.label} of ${input.entry.scope}; no value and no copy remains behind the seam.` };
12519
+ }
12520
+ function vaultcovers(entry, origin) {
12521
+ return entry.scope === origin;
12522
+ }
12523
+ async function secretleakscan(input) {
12524
+ const leaks = [];
12525
+ for (const candidate of input.candidates) {
12526
+ if (candidate.trim() === "") continue;
12527
+ const digest = await vaultdigestof(candidate);
12528
+ if (input.entries.some((entry) => entry.digest === digest)) leaks.push(candidate);
12529
+ }
12530
+ if (leaks.length > 0) return { leaks, reason: `The plan carries ${leaks.length} plaintext value${leaks.length === 1 ? "" : "s"} that digest to vault records; secrets never ride step options, variables or plan texts, only the vault holds them.` };
12531
+ return { leaks: [], reason: "No candidate value digests to a vault record; the plan carries no leaked secret." };
12532
+ }
12533
+ function stepoptions4(step) {
12534
+ if (!step.options) return {};
12535
+ try {
12536
+ const parsed = JSON.parse(step.options);
12537
+ return Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
12538
+ } catch {
12539
+ return {};
12540
+ }
12541
+ }
12542
+ function secretshapecarrying(step) {
12543
+ const options = stepoptions4(step);
12544
+ const fields = Array.isArray(options.fields) ? options.fields.filter((item) => Boolean(item) && typeof item === "object") : [];
12545
+ const rawfield = fields.find((field) => typeof field.name === "string" && typeof field.value === "string" && field.value !== "" && maskingfield(field.name, []));
12546
+ if (rawfield !== void 0) return { carries: true, reason: `The ${step.kind} step types a raw value into the ${String(rawfield.name)} field; credential steps read their value from the vault at the last possible moment and never carry it in the options.` };
12547
+ if (typeof options.field === "string" && maskingfield(options.field, []) && step.value !== void 0 && step.value !== "") return { carries: true, reason: `The ${step.kind} step types a raw value into the ${options.field} field; credential steps read their value from the vault at the last possible moment and never carry it in the options.` };
12548
+ return { carries: false, reason: "The step carries no raw value behind a masked field shape." };
12549
+ }
12550
+ function vaultview(entries) {
12551
+ return entries.map((entry) => ({ vaultid: entry.vaultid, label: entry.label, scope: entry.scope, provenance: entry.provenance, createdat: entry.createdat, ...entry.lastusedat !== void 0 ? { lastusedat: entry.lastusedat } : {} }));
12552
+ }
12553
+ function vaultprompttext(entry, origin) {
12554
+ return `Use the credential ${entry.label} of ${entry.scope} on ${origin}? The value stays behind the vault and no surface ever displays it.`;
12555
+ }
12556
+
11924
12557
  // taskqueue.ts
11925
12558
  function emptyqueue(input = {}) {
11926
12559
  return { lanes: input.lanes ?? [], priorities: input.priorities ?? [], completionpolicy: input.completionpolicy ?? "all", items: [], claims: [] };
@@ -12016,6 +12649,40 @@ function taskcounts(queue) {
12016
12649
  };
12017
12650
  }
12018
12651
 
12652
+ // transparency.ts
12653
+ function permissiondiff(input) {
12654
+ if (input.fromversion.trim() === "" || input.toversion.trim() === "") throw new Error("The permdiff names the two versions it compares.");
12655
+ const added = [...new Set(input.to.filter((permission) => !input.from.includes(permission)))];
12656
+ const removed = [...new Set(input.from.filter((permission) => !input.to.includes(permission)))];
12657
+ return { fromversion: input.fromversion, toversion: input.toversion, added, removed, computedat: input.now };
12658
+ }
12659
+ function permdiffchanged(diff) {
12660
+ return diff.added.length > 0 || diff.removed.length > 0;
12661
+ }
12662
+ function permdiffsummary(diff) {
12663
+ if (!permdiffchanged(diff)) return `The update from ${diff.fromversion} to ${diff.toversion} changed no permission.`;
12664
+ const parts = [];
12665
+ if (diff.added.length > 0) parts.push(`added ${diff.added.join(", ")}`);
12666
+ if (diff.removed.length > 0) parts.push(`removed ${diff.removed.join(", ")}`);
12667
+ return `The update from ${diff.fromversion} to ${diff.toversion} ${parts.join(" and ")}.`;
12668
+ }
12669
+ function transparencygrants(input) {
12670
+ const grants = input.allowlist.map((entry) => ({ origin: entry.origin, scope: `automation allowlist of the profile workspace ${entry.profileid}`, boundary: "the user revokes the entry or the profile workspace", grantedat: entry.grantedat }));
12671
+ for (const profile of input.profiles) {
12672
+ grants.push({ origin: profile.origin, scope: `origin profile with ${profile.grants.length} granted and ${profile.denials.length} denied kinds`, boundary: "the user edits or revokes the profile", grantedat: profile.createdat });
12673
+ }
12674
+ return grants;
12675
+ }
12676
+ function revokeaction(grant) {
12677
+ return { action: "revoke", origin: grant.origin, scope: grant.scope };
12678
+ }
12679
+ function windowhistory(windows) {
12680
+ return windows.map((window) => ({ id: window.id, origin: window.origin, state: window.state, boundary: window.boundary, startedat: window.startedat, expiresat: window.expiresat }));
12681
+ }
12682
+ function connectallowlist(entries) {
12683
+ return entries.map((entry) => ({ senderid: entry.senderid, displayname: entry.displayname, ...entry.origin !== void 0 ? { origin: entry.origin } : {}, addedat: entry.addedat }));
12684
+ }
12685
+
12019
12686
  // protocol.ts
12020
12687
  function record(value) {
12021
12688
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Protocol message must be an object.");
@@ -12837,6 +13504,9 @@ function securityreport(input) {
12837
13504
  function logchainreport(input) {
12838
13505
  return { version: protocolversion, runid: input.runid, valid: input.valid, entries: input.entries, ...input.brokenat !== void 0 ? { brokenat: input.brokenat } : {}, reason: input.reason, ...input.sealhash !== void 0 ? { sealhash: input.sealhash } : {}, ...input.sealedat !== void 0 ? { sealedat: input.sealedat } : {} };
12839
13506
  }
13507
+ function transparencyreport(input) {
13508
+ return { version: protocolversion, posture: "denydefault", grants: input.grants, windows: input.windows, connectallow: input.connectallow, permdiffs: input.permdiffs, safedefaults: input.safedefaults, vault: input.vault };
13509
+ }
12840
13510
 
12841
13511
  // workfloweditor.ts
12842
13512
  var palettecategories = ["actions", "controlflow", "waits", "variables", "triggers"];
@@ -13623,6 +14293,9 @@ export {
13623
14293
  breakpointinputof,
13624
14294
  broadcastrecipient,
13625
14295
  browserpermissions,
14296
+ bucketboundsvalid,
14297
+ bucketconsume,
14298
+ bucketof,
13626
14299
  budgetcheck,
13627
14300
  buildname,
13628
14301
  buildpdf,
@@ -13656,6 +14329,7 @@ export {
13656
14329
  capturesourcemaps,
13657
14330
  capturestates,
13658
14331
  capturestitched,
14332
+ capturesurfaceof,
13659
14333
  capturetargets,
13660
14334
  capturevisible,
13661
14335
  castvote,
@@ -13686,7 +14360,13 @@ export {
13686
14360
  complete,
13687
14361
  composeworkflow,
13688
14362
  conditionof,
14363
+ confirmcredsgate,
14364
+ confirmdeletegate,
13689
14365
  confirmmanualrun,
14366
+ confirmpaygate,
14367
+ connectallowentryof,
14368
+ connectallowgate,
14369
+ connectallowlist,
13690
14370
  connectclient,
13691
14371
  consensusstate,
13692
14372
  consentdurationvalid,
@@ -13713,6 +14393,8 @@ export {
13713
14393
  costbudgetvalid,
13714
14394
  cpusnap,
13715
14395
  crashinterrupted,
14396
+ credentialstep,
14397
+ credspayload,
13716
14398
  cronnext,
13717
14399
  cronparse,
13718
14400
  croprect,
@@ -13737,7 +14419,10 @@ export {
13737
14419
  defaultrefusalmarkers,
13738
14420
  defaulttokenlifetimems,
13739
14421
  defaulttriggercooldown,
14422
+ deferredeventof,
14423
+ deferredready,
13740
14424
  delayjitter,
14425
+ deletepayload,
13741
14426
  deniedevidenceof,
13742
14427
  denydefaultnotice,
13743
14428
  denydefaultposture,
@@ -13764,6 +14449,7 @@ export {
13764
14449
  egressconsentgate,
13765
14450
  electleader,
13766
14451
  emptyboard,
14452
+ emptyconnectallow,
13767
14453
  emptyqueue,
13768
14454
  emugate,
13769
14455
  emulationkinds,
@@ -13776,6 +14462,7 @@ export {
13776
14462
  enqueuerequest,
13777
14463
  entryfresh,
13778
14464
  entryhashof,
14465
+ envelopecheck,
13779
14466
  environmentgrammar,
13780
14467
  environmentgrantgate,
13781
14468
  environmentreport,
@@ -13820,6 +14507,7 @@ export {
13820
14507
  fetchoptionsof,
13821
14508
  fetchrequestof,
13822
14509
  fieldshapekind,
14510
+ fieldshaperegions,
13823
14511
  filteredsessions,
13824
14512
  filterentries,
13825
14513
  filterexchanges,
@@ -13832,6 +14520,11 @@ export {
13832
14520
  formreportresponse,
13833
14521
  framedlog,
13834
14522
  frameinterval,
14523
+ gatebatchgate,
14524
+ gateforstep,
14525
+ gatekindfor,
14526
+ gateprompttext,
14527
+ gatestateof,
13835
14528
  generatedvalueallowed,
13836
14529
  grantallowlistentry,
13837
14530
  graphqlopenvelope,
@@ -13868,6 +14561,7 @@ export {
13868
14561
  inflightreport,
13869
14562
  inheritconsent,
13870
14563
  initialize,
14564
+ inmemoryvault,
13871
14565
  interleavetimeline,
13872
14566
  iscdpkind,
13873
14567
  iscontrolflowkind,
@@ -13920,6 +14614,7 @@ export {
13920
14614
  loglevels,
13921
14615
  logreadgate,
13922
14616
  longtaskcapture,
14617
+ lookalikedistance,
13923
14618
  loopof,
13924
14619
  mailboxof,
13925
14620
  manualpreview,
@@ -13947,6 +14642,7 @@ export {
13947
14642
  mediaentries,
13948
14643
  mediakinds,
13949
14644
  mediareport,
14645
+ mergeregions,
13950
14646
  mergeresults,
13951
14647
  messageegressgrade,
13952
14648
  messagefilterof,
@@ -13979,6 +14675,7 @@ export {
13979
14675
  newsessionrecord,
13980
14676
  newworkflowrun,
13981
14677
  nextrequest,
14678
+ nobatchresolution,
13982
14679
  nonceof,
13983
14680
  normalizeendpoint,
13984
14681
  oauthflowof,
@@ -13991,12 +14688,16 @@ export {
13991
14688
  openchannel,
13992
14689
  openconsensus,
13993
14690
  openconsentwindow,
14691
+ opengate,
13994
14692
  openoffscreen,
13995
14693
  openrun,
13996
14694
  openrunlog,
13997
14695
  openseal,
13998
14696
  openstreamchannel,
13999
14697
  opentabagent,
14698
+ origincheckgate,
14699
+ origincheckof,
14700
+ originlabels,
14000
14701
  originprofilegate,
14001
14702
  originprofileof,
14002
14703
  outcomeresponse,
@@ -14029,15 +14730,24 @@ export {
14029
14730
  payloadshapeof,
14030
14731
  payloadvalid,
14031
14732
  payloadwithdefaults,
14733
+ paypayload,
14032
14734
  pdfoptionsof,
14033
14735
  pdfpagesize,
14034
14736
  pdfsegments,
14035
14737
  pdftextlayout,
14738
+ permdiffchanged,
14739
+ permdiffsummary,
14740
+ permissiondiff,
14036
14741
  permissiongrade,
14037
14742
  permissiongrantof,
14038
14743
  permissionnamevalid,
14039
14744
  permissionstates,
14040
14745
  permissionstatevalid,
14746
+ phishguardgate,
14747
+ phishnotetext,
14748
+ phishthresholdgate,
14749
+ phishthresholdvalid,
14750
+ phishverdictof,
14041
14751
  ping,
14042
14752
  planallowlist,
14043
14753
  plandraftreviewgate,
@@ -14048,6 +14758,7 @@ export {
14048
14758
  pollurl,
14049
14759
  poolplan,
14050
14760
  popscope,
14761
+ portaccept,
14051
14762
  postentry,
14052
14763
  preparehandoff,
14053
14764
  privatemime,
@@ -14076,7 +14787,9 @@ export {
14076
14787
  queuelanesvalid,
14077
14788
  randomid,
14078
14789
  rankapis,
14790
+ ratelimitboundsvalid,
14079
14791
  ratelimitbudgetallowed,
14792
+ ratelimitgate,
14080
14793
  ratelimitreadof,
14081
14794
  ratelimitreport,
14082
14795
  ratelimitwait,
@@ -14097,6 +14810,8 @@ export {
14097
14810
  recoveryplan,
14098
14811
  redactconsoletext,
14099
14812
  redactedcookies,
14813
+ redactedshot,
14814
+ redactionsummary,
14100
14815
  redactparams,
14101
14816
  redeempairingcode,
14102
14817
  redoedit,
@@ -14104,7 +14819,10 @@ export {
14104
14819
  reflectstep,
14105
14820
  regexextract,
14106
14821
  regexruleof,
14822
+ regionof,
14823
+ regionsfor,
14107
14824
  regionsteps,
14825
+ regionvalid,
14108
14826
  registeragent,
14109
14827
  rejectioncapture,
14110
14828
  relayframe,
@@ -14135,6 +14853,7 @@ export {
14135
14853
  resolveapproval,
14136
14854
  resolvedrisk,
14137
14855
  resolveescalation,
14856
+ resolvegate,
14138
14857
  resolverecipients,
14139
14858
  resolveroute,
14140
14859
  resolvetool,
@@ -14159,6 +14878,7 @@ export {
14159
14878
  reviewedkinds,
14160
14879
  reviewframe,
14161
14880
  revocationruleof,
14881
+ revokeaction,
14162
14882
  revokeclient,
14163
14883
  revokerun,
14164
14884
  revokerungate,
@@ -14190,6 +14910,10 @@ export {
14190
14910
  runurllist,
14191
14911
  runwhile,
14192
14912
  runworkflow,
14913
+ safedefaultnotice,
14914
+ safedefaultprofile,
14915
+ safedefaultreadkind,
14916
+ safedefaultsgate,
14193
14917
  safetyresponse,
14194
14918
  samplingframes,
14195
14919
  sandboxorigingate,
@@ -14201,6 +14925,8 @@ export {
14201
14925
  scanconflicts,
14202
14926
  schedulecron,
14203
14927
  scheduleinterval,
14928
+ schemacheck,
14929
+ schemaguardgate,
14204
14930
  scopecheck,
14205
14931
  scopegate,
14206
14932
  scopegrantof,
@@ -14212,6 +14938,8 @@ export {
14212
14938
  searchsessionrecords,
14213
14939
  searchsteps,
14214
14940
  searchtemplates,
14941
+ secretleakscan,
14942
+ secretshapecarrying,
14215
14943
  securityreport,
14216
14944
  seededrandom,
14217
14945
  selectorresponse,
@@ -14293,6 +15021,7 @@ export {
14293
15021
  taskstatevalid,
14294
15022
  teardowncdpsession,
14295
15023
  teardownplanof,
15024
+ templateof,
14296
15025
  templateurl,
14297
15026
  templatevariables,
14298
15027
  thumbdirectiveof,
@@ -14332,6 +15061,8 @@ export {
14332
15061
  transferablekeys,
14333
15062
  transferhandoff,
14334
15063
  transformgrammar,
15064
+ transparencygrants,
15065
+ transparencyreport,
14335
15066
  triggereventcatalog,
14336
15067
  triggerfamilies,
14337
15068
  triggerfamilyof,
@@ -14345,6 +15076,7 @@ export {
14345
15076
  tryof,
14346
15077
  undoedit,
14347
15078
  unreadcount,
15079
+ untrustedrendergate,
14348
15080
  unwrapgraphql,
14349
15081
  updaterule,
14350
15082
  urlencodeform,
@@ -14361,6 +15093,17 @@ export {
14361
15093
  validatetoolcatalog,
14362
15094
  validatevaluegen,
14363
15095
  validateworkflow,
15096
+ vaultcovers,
15097
+ vaultdelete,
15098
+ vaultdigestof,
15099
+ vaultdigestprefix,
15100
+ vaultentryof,
15101
+ vaultprompttext,
15102
+ vaultsecretgate,
15103
+ vaultstore,
15104
+ vaultvaluefor,
15105
+ vaultview,
15106
+ verdictfresh,
14364
15107
  verifyauth,
14365
15108
  verifylogchain,
14366
15109
  verifytoken,
@@ -14377,6 +15120,7 @@ export {
14377
15120
  whileof,
14378
15121
  wildcardentry,
14379
15122
  windowgatesstep,
15123
+ windowhistory,
14380
15124
  wireformat,
14381
15125
  wizardreport,
14382
15126
  workerpoolsizevalid,