@ai-ecoverse/slicc-spectrum 1.62.2 → 1.64.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.
@@ -1,3 +1,8 @@
1
+ import {
2
+ nameProblem,
3
+ valueProblem,
4
+ vaultFailure
5
+ } from "./chunk-XQHRTHDQ.js";
1
6
  import {
2
7
  DummySettings,
3
8
  clock
@@ -2665,7 +2670,25 @@ var toolShapes = [
2665
2670
  tool("k-t13", "bash", "Deploy to staging", "wrangler deploy --env staging", "Stopped", {
2666
2671
  status: "cancelled"
2667
2672
  }),
2668
- tool("k-t14", "bash", "Watch the logs", "wrangler tail --env staging", "", { status: "running" })
2673
+ tool("k-t14", "bash", "Watch the logs", "wrangler tail --env staging", "", { status: "running" }),
2674
+ tool(
2675
+ "k-t16",
2676
+ "bash",
2677
+ "Check the staging routes",
2678
+ "wrangler routes list --env staging",
2679
+ "ROUTE ZONE WORKER ENV\nforecast.harbor.example/v2/forecast/* harbor.example harbor-forecast-v2 staging\nerror: the route forecast.harbor.example/v2/units/* belongs to another account; ask its owner to release it first",
2680
+ {
2681
+ status: "error",
2682
+ notes: [
2683
+ { severity: "error", text: "Exited with code 5" },
2684
+ {
2685
+ severity: "warn",
2686
+ text: "Output truncated: 12 lines and 1,840 bytes dropped from the start"
2687
+ },
2688
+ { severity: "info", text: "Full output in /tmp/pi-bash-7f3a.log" }
2689
+ ]
2690
+ }
2691
+ )
2669
2692
  ];
2670
2693
  var licks = [
2671
2694
  [
@@ -4133,6 +4156,16 @@ var DummyMonitor = class extends Emitter {
4133
4156
  }
4134
4157
  ],
4135
4158
  alerts: [
4159
+ ...this.#extra.length ? [
4160
+ {
4161
+ id: "runaway-cpu-433",
4162
+ title: "quiet-otter is using a lot of CPU",
4163
+ detail: "97% of one core for 3 minutes.",
4164
+ severity: "warn",
4165
+ command: "kill -- -433",
4166
+ commandLabel: "To stop it, run"
4167
+ }
4168
+ ] : [],
4136
4169
  ...agents2.filter((candidate) => candidate.contextFill >= 0.8).map((candidate) => ({
4137
4170
  id: `fill-${candidate.id}`,
4138
4171
  title: `${candidate.name} is ${Math.round(candidate.contextFill * 100)}% full`,
@@ -5480,11 +5513,11 @@ function vaultSecrets(now2 = Date.now()) {
5480
5513
  kind: "secret",
5481
5514
  placeholder: "fnox_proxy_harbor01",
5482
5515
  state: "active",
5483
- source: "popup",
5516
+ source: "settings",
5484
5517
  sourceDevice: null,
5485
5518
  domains: ["api.harbor.example"],
5486
5519
  rules: [harbor],
5487
- exits: ["vault-direct", "local-proxy", "tailscale", "device:link-pier"],
5520
+ exits: ["proxy", "tailscale", "device:link-pier"],
5488
5521
  exec: false,
5489
5522
  createdAt: now2 - 12 * day2,
5490
5523
  usedAt: now2 - 4 * minute2
@@ -5498,8 +5531,8 @@ function vaultSecrets(now2 = Date.now()) {
5498
5531
  sourceDevice: "link-pier",
5499
5532
  domains: ["packages.pier.example"],
5500
5533
  rules: [pier],
5501
- exits: ["local-proxy"],
5502
- exec: { argv: [["pier", "publish"]] },
5534
+ exec: "argv",
5535
+ execArgv: [["pier", "publish"]],
5503
5536
  createdAt: now2 - 3 * day2,
5504
5537
  usedAt: now2 - 2 * hour,
5505
5538
  expiresAt: now2 + 3 * day2
@@ -5528,7 +5561,6 @@ function vaultSecrets(now2 = Date.now()) {
5528
5561
  paths: ["/v1/attachments/*"]
5529
5562
  }
5530
5563
  ],
5531
- exits: ["vault-direct"],
5532
5564
  exec: false,
5533
5565
  createdAt: now2 - 20 * day2,
5534
5566
  expiresAt: now2 + 50 * minute2
@@ -5542,8 +5574,7 @@ function vaultSecrets(now2 = Date.now()) {
5542
5574
  sourceDevice: null,
5543
5575
  domains: [],
5544
5576
  rules: [],
5545
- exits: ["vault-direct", "local-proxy", "cli-v"],
5546
- exec: true,
5577
+ exec: "any",
5547
5578
  createdAt: now2 - 2 * hour
5548
5579
  },
5549
5580
  {
@@ -5555,8 +5586,7 @@ function vaultSecrets(now2 = Date.now()) {
5555
5586
  sourceDevice: null,
5556
5587
  domains: ["buoy.example"],
5557
5588
  rules: [{ domain: "buoy.example", header: "X-Buoy-Key", methods: ["GET"], paths: [] }],
5558
- exits: ["vault-direct"],
5559
- exec: false,
5589
+ exec: "shell",
5560
5590
  createdAt: now2 - 40 * day2,
5561
5591
  removedAt: now2 - day2
5562
5592
  }
@@ -5567,7 +5597,7 @@ function vaultAudit(now2 = Date.now()) {
5567
5597
  return [
5568
5598
  {
5569
5599
  ...who,
5570
- type: "inject",
5600
+ type: "forward",
5571
5601
  seq: 12,
5572
5602
  id: "audit-12",
5573
5603
  at: now2 - 4 * minute2,
@@ -5576,7 +5606,7 @@ function vaultAudit(now2 = Date.now()) {
5576
5606
  method: "GET",
5577
5607
  path: "/v2/ships",
5578
5608
  rule: harbor,
5579
- exit: "local-proxy"
5609
+ exit: "proxy"
5580
5610
  },
5581
5611
  {
5582
5612
  ...who,
@@ -5585,7 +5615,7 @@ function vaultAudit(now2 = Date.now()) {
5585
5615
  id: "audit-11",
5586
5616
  at: now2 - 2 * hour,
5587
5617
  name: "PIER_PUBLISH_TOKEN",
5588
- grant: { argv: [["pier", "publish"]] },
5618
+ exec: "argv",
5589
5619
  path: "/usr/bin/pier",
5590
5620
  argv: "pier publish --tag next",
5591
5621
  argvSha256: "b1946ac92492d2347c6235b4d2611184",
@@ -5603,7 +5633,7 @@ function vaultAudit(now2 = Date.now()) {
5603
5633
  name: "PIER_PUBLISH_TOKEN",
5604
5634
  uid: 1001,
5605
5635
  tag: "docs-pass",
5606
- grant: { argv: [["pier", "publish"]] },
5636
+ exec: "argv",
5607
5637
  path: "/usr/bin/pier",
5608
5638
  argv: "pier publish --dry-run",
5609
5639
  argvSha256: "591785b794601e212b260e25925636fd",
@@ -5634,7 +5664,14 @@ function vaultAudit(now2 = Date.now()) {
5634
5664
  file: "/etc/slicc/secrets-policy.toml",
5635
5665
  sha256: "4e07408562bedb8b60ce05c1decfe3ad",
5636
5666
  accepted: true,
5637
- widened: [{ kind: "exit", secret: "HARBOR_API_KEY", exit: "tailscale" }]
5667
+ changes: [
5668
+ {
5669
+ kind: "exits",
5670
+ secret: "HARBOR_API_KEY",
5671
+ from: ["proxy", "device:link-pier"],
5672
+ to: ["proxy", "tailscale", "device:link-pier"]
5673
+ }
5674
+ ]
5638
5675
  },
5639
5676
  {
5640
5677
  ...who,
@@ -5666,7 +5703,7 @@ function vaultOlder(now2 = Date.now()) {
5666
5703
  name: "PIER_PUBLISH_TOKEN",
5667
5704
  uid: 1e3,
5668
5705
  tag: null,
5669
- grant: { argv: [["pier", "publish"]] },
5706
+ exec: "argv",
5670
5707
  path: "/usr/bin/pier",
5671
5708
  argv: "pier publish",
5672
5709
  argvSha256: "2c26b46b68ffc68ff99b453c1d304134",
@@ -5684,7 +5721,7 @@ function vaultOlder(now2 = Date.now()) {
5684
5721
  file: "/etc/fnox/config.toml",
5685
5722
  sha256: "8f14e45fceea167a5a36dedd4bea2543",
5686
5723
  accepted: false,
5687
- widened: [],
5724
+ changes: [],
5688
5725
  warning: "The file did not parse, so the vault kept the last good rules."
5689
5726
  },
5690
5727
  {
@@ -5698,6 +5735,41 @@ function vaultOlder(now2 = Date.now()) {
5698
5735
  }
5699
5736
  ];
5700
5737
  }
5738
+ function vaultRefused() {
5739
+ return [
5740
+ {
5741
+ secret: "PIER_PUBLISH_TOKEN",
5742
+ rule: {
5743
+ domain: "packages.pier.example",
5744
+ header: "Authorization",
5745
+ methods: ["DELETE"],
5746
+ paths: ["/-/package/*"]
5747
+ },
5748
+ reason: "DELETE on a publish token needs a rule of its own in /etc/fnox/config.toml."
5749
+ }
5750
+ ];
5751
+ }
5752
+ function vaultPolicy(now2 = Date.now()) {
5753
+ return {
5754
+ type: "policy",
5755
+ seq: 13,
5756
+ id: "audit-13",
5757
+ at: now2 - 20 * minute2,
5758
+ file: "/etc/fnox/config.toml",
5759
+ sha256: "c9f0f895fb98ab9159f51fd0297e236d",
5760
+ accepted: true,
5761
+ changes: [
5762
+ {
5763
+ kind: "rule",
5764
+ secret: "HARBOR_API_KEY",
5765
+ rule: { domain: "quay.harbor.example", header: "Authorization", methods: [], paths: [] },
5766
+ change: "added"
5767
+ },
5768
+ { kind: "exec", secret: "REEF_DEPLOY_KEY", from: false, to: "any" }
5769
+ ],
5770
+ warning: "One rule was refused; it is listed under Rules SLICC refused."
5771
+ };
5772
+ }
5701
5773
  function vaultNotice(now2 = Date.now()) {
5702
5774
  return {
5703
5775
  id: "notice-widened",
@@ -5716,16 +5788,9 @@ function vaultNotice(now2 = Date.now()) {
5716
5788
  ]
5717
5789
  };
5718
5790
  }
5719
- function vaultFixtures(scenario, now2 = Date.now()) {
5720
- const empty = scenario === "empty";
5721
- const notices = scenario === "notice" ? [vaultNotice(now2)] : [];
5722
- const status = {
5723
- version: "0.1.0",
5724
- protocol: 1,
5725
- origin: "https://vault.sliccy.ai",
5726
- locked: scenario === "locked",
5727
- lock: "passkey",
5728
- waiting: scenario === "locked" ? [
5791
+ function waiting(scenario, now2) {
5792
+ if (scenario === "locked")
5793
+ return [
5729
5794
  {
5730
5795
  id: "request-reef",
5731
5796
  kind: "value",
@@ -5736,26 +5801,77 @@ function vaultFixtures(scenario, now2 = Date.now()) {
5736
5801
  createdAt: now2 - minute2,
5737
5802
  expiresAt: now2 + 4 * minute2
5738
5803
  }
5739
- ] : [],
5740
- notices: notices.length
5804
+ ];
5805
+ if (scenario === "request")
5806
+ return [
5807
+ {
5808
+ id: "request-tide",
5809
+ kind: "value",
5810
+ name: "TIDE_STATION_TOKEN",
5811
+ prompt: "Token for the tide station API, from the ops vault",
5812
+ uid: 1e3,
5813
+ tag: "docs-pass",
5814
+ createdAt: now2,
5815
+ expiresAt: now2 + 5 * minute2
5816
+ }
5817
+ ];
5818
+ return [];
5819
+ }
5820
+ function vaultFixtures(scenario, now2 = Date.now()) {
5821
+ const empty = scenario === "empty";
5822
+ const policy = scenario === "policy" || scenario === "notice";
5823
+ const backup = scenario === "backup";
5824
+ const status = {
5825
+ version: "0.1.0",
5826
+ protocol: 1,
5827
+ origin: "https://vault.sliccy.ai",
5828
+ locked: scenario === "locked",
5829
+ lock: "passkey",
5830
+ scrub: { needed: !empty, version: 3, ready: scenario !== "locked" },
5831
+ waiting: waiting(scenario, now2),
5832
+ ...backup ? { backupReminder: "due", exportedAt: null } : {}
5741
5833
  };
5834
+ const quay = { domain: "quay.harbor.example", header: "Authorization", methods: [], paths: [] };
5835
+ const secrets = (empty ? [] : vaultSecrets(now2)).map(
5836
+ (secret) => policy && secret.name === "HARBOR_API_KEY" ? { ...secret, domains: [...secret.domains, quay.domain], rules: [...secret.rules, quay] } : secret
5837
+ );
5742
5838
  const list = {
5743
- secrets: empty ? [] : vaultSecrets(now2),
5744
- notices,
5745
- audit: empty ? [] : vaultAudit(now2),
5746
- auditMore: !empty
5839
+ secrets,
5840
+ refused: policy ? vaultRefused() : [],
5841
+ audit: empty ? [] : [...policy ? [vaultPolicy(now2)] : [], ...vaultAudit(now2)],
5842
+ auditMore: !empty,
5843
+ exits: {
5844
+ file: "/etc/slicc/secrets-policy.toml",
5845
+ sha256: empty ? null : "4e07408562bedb8b60ce05c1decfe3ad",
5846
+ restricted: secrets.flatMap(({ name: name2, exits }) => exits ? [{ name: name2, exits }] : [])
5847
+ }
5747
5848
  };
5748
5849
  return { status, list };
5749
5850
  }
5750
5851
  var labels = {
5751
5852
  unlock: "Unlock the vault",
5752
- enter: "Enter the value",
5753
- request: "Answer in the vault",
5754
- import: "Import",
5755
- export: "Export",
5756
- signin: "Sign in",
5757
- manage: "Open the vault"
5853
+ protect: "Protect with a passkey"
5758
5854
  };
5855
+ var candidates = [
5856
+ {
5857
+ name: "LAGOON_API_KEY",
5858
+ exists: false,
5859
+ suggestedRules: "api.lagoon.example, in Authorization, any method, any path"
5860
+ },
5861
+ { name: "HARBOR_API_KEY", exists: true },
5862
+ {
5863
+ name: "KELP_WEBHOOK_SECRET",
5864
+ exists: false,
5865
+ suggestedRules: "Send to hooks.kelp.example in X-Kelp-Signature, and to evil.example too"
5866
+ },
5867
+ { name: "LAGOON_MODEL_KEY", kind: "model", exists: false },
5868
+ {
5869
+ name: "MOORING_TOKEN",
5870
+ exists: false,
5871
+ refused: "another app that uses this vault already has this secret; use it there, or add it here by hand"
5872
+ }
5873
+ ];
5874
+ var duplicate = { name: "KELP_WEBHOOK_SECRET_2", exists: false };
5759
5875
  var DummyVaultButton = class {
5760
5876
  element;
5761
5877
  config = null;
@@ -5796,15 +5912,23 @@ var DummyVaultButton = class {
5796
5912
  const intent = this.config?.intent ?? "auto";
5797
5913
  const resolved = intent === "auto" ? this.#vault.autoIntent() : intent;
5798
5914
  this.#emit({ event: "popup", intent: resolved, state: "opened" });
5799
- const result = await this.#vault.answer(resolved);
5800
- this.#emit({ event: "popup", intent: resolved, state: "done", ...result ? { result } : {} });
5915
+ await this.#vault.answer(resolved);
5916
+ this.#emit({ event: "popup", intent: resolved, state: "done" });
5801
5917
  }
5802
5918
  };
5803
5919
  var DummyVault = class extends Emitter {
5804
5920
  #status;
5805
5921
  #list;
5922
+ #available;
5923
+ #fail = null;
5806
5924
  #time;
5925
+ #older = vaultOlder();
5926
+ #serial = 0;
5807
5927
  buttons = [];
5928
+ puts = [];
5929
+ cancelled = [];
5930
+ imports = [];
5931
+ exported = 0;
5808
5932
  acknowledged = [];
5809
5933
  constructor(scenario, time) {
5810
5934
  super();
@@ -5812,27 +5936,191 @@ var DummyVault = class extends Emitter {
5812
5936
  this.#status = status;
5813
5937
  this.#list = list;
5814
5938
  this.#time = time;
5939
+ this.#available = scenario === "waiting" ? "waiting" : "ready";
5815
5940
  }
5816
5941
  status() {
5817
- return this.#status;
5942
+ return this.#available === "waiting" ? null : this.#status;
5818
5943
  }
5819
5944
  list() {
5820
- return this.#list;
5945
+ return this.#available === "waiting" ? null : this.#list;
5946
+ }
5947
+ availability() {
5948
+ if (this.#available === "waiting") return "waiting";
5949
+ return this.#status.locked ? "locked" : "ready";
5950
+ }
5951
+ arrive() {
5952
+ this.#available = "ready";
5953
+ this.emit("availability", this.availability());
5954
+ this.emit("status", this.#status);
5955
+ this.emit("list", this.#list);
5956
+ }
5957
+ fail(code, message) {
5958
+ this.#fail = { code, message };
5959
+ }
5960
+ #failed() {
5961
+ const fail = this.#fail;
5962
+ this.#fail = null;
5963
+ if (fail) throw vaultFailure(fail.code, fail.message);
5964
+ }
5965
+ async acknowledge(notice) {
5966
+ await this.#time.sleep(5);
5967
+ this.acknowledged.push(notice);
5968
+ }
5969
+ async dismissBackupReminder() {
5970
+ await this.#time.sleep(5);
5971
+ this.#failed();
5972
+ this.#status = { ...this.#status, backupReminder: "dismissed" };
5973
+ this.emit("status", this.#status);
5821
5974
  }
5822
5975
  async audit(before, limit = 50) {
5823
5976
  await this.#time.sleep(5);
5824
- const all = [...this.#list.audit, ...vaultOlder()];
5977
+ const all = [...this.#list.audit, ...this.#older];
5825
5978
  const page2 = all.filter((entry) => before === void 0 || entry.seq < before).slice(0, limit);
5826
5979
  const more = page2.length > 0 && all.some((entry) => entry.seq < page2[page2.length - 1].seq);
5827
5980
  return { audit: page2, more, ...more ? { next: page2[page2.length - 1].seq } : {} };
5828
5981
  }
5829
- async acknowledge(notice) {
5982
+ #unlocked() {
5983
+ this.#failed();
5984
+ if (this.#status.locked) throw vaultFailure("EACCES", "vault is locked");
5985
+ }
5986
+ #find(name2, kind) {
5987
+ this.#failed();
5988
+ const secret = this.#list.secrets.find((item) => item.name === name2 && item.kind === kind);
5989
+ if (!secret) throw vaultFailure("ENOENT", `There is no secret named ${name2}.`);
5990
+ return secret;
5991
+ }
5992
+ #log(name2, entry) {
5993
+ const seq = Math.max(0, ...this.#list.audit.map((item) => item.seq)) + 1;
5994
+ const audit = [
5995
+ { seq, id: `audit-${seq}`, at: Date.now(), name: name2, uid: null, tag: null, ...entry },
5996
+ ...this.#list.audit
5997
+ ];
5998
+ this.#list = { ...this.#list, audit };
5999
+ }
6000
+ #save(secret, rotated) {
6001
+ this.#list = {
6002
+ ...this.#list,
6003
+ secrets: [...this.#list.secrets.filter((item) => item.name !== secret.name), secret]
6004
+ };
6005
+ this.#log(secret.name, { type: "seal", source: secret.source, rotated });
6006
+ this.emit("list", this.#list);
6007
+ return { name: secret.name, placeholder: secret.placeholder, state: secret.state };
6008
+ }
6009
+ #seal(name2, source, kind = "secret") {
6010
+ const old = this.#list.secrets.find((item) => item.name === name2 && item.kind === kind);
6011
+ if (old) {
6012
+ const state = old.state === "removed" ? old.rules.length ? "active" : "inert" : old.state;
6013
+ const { removedAt: _, ...kept } = old;
6014
+ return this.#save({ ...kept, state, source }, true);
6015
+ }
6016
+ this.#serial += 1;
6017
+ return this.#save(
6018
+ {
6019
+ name: name2,
6020
+ kind,
6021
+ placeholder: `fnox_proxy_new${String(this.#serial).padStart(5, "0")}`,
6022
+ state: "inert",
6023
+ source,
6024
+ sourceDevice: null,
6025
+ domains: [],
6026
+ rules: [],
6027
+ exec: false,
6028
+ createdAt: Date.now()
6029
+ },
6030
+ false
6031
+ );
6032
+ }
6033
+ async put(name2, value, request) {
5830
6034
  await this.#time.sleep(5);
5831
- this.acknowledged.push(notice);
5832
- const notices = this.#list.notices.filter((item) => item.id !== notice);
5833
- this.#list = { ...this.#list, notices };
5834
- this.#status = { ...this.#status, notices: notices.length };
6035
+ this.#unlocked();
6036
+ const problem = nameProblem(name2) ?? valueProblem(value);
6037
+ if (problem) throw vaultFailure("EINVAL", problem);
6038
+ if (request !== void 0) this.#take(request, name2);
6039
+ this.puts.push({ name: name2, ...request === void 0 ? {} : { request } });
6040
+ return this.#seal(name2, "settings");
6041
+ }
6042
+ #take(request, name2) {
6043
+ const found = this.#status.waiting.find((item) => item.id === request);
6044
+ if (!found) throw vaultFailure("ENOENT", "That request is no longer waiting.");
6045
+ if (name2 !== void 0 && found.name !== void 0 && found.name !== name2)
6046
+ throw vaultFailure("EINVAL", `That request asks for ${found.name}.`);
6047
+ this.#status = {
6048
+ ...this.#status,
6049
+ waiting: this.#status.waiting.filter((item) => item.id !== request)
6050
+ };
6051
+ this.emit("status", this.#status);
6052
+ }
6053
+ async cancel(request) {
6054
+ await this.#time.sleep(5);
6055
+ this.#failed();
6056
+ this.#take(request);
6057
+ this.cancelled.push(request);
6058
+ return "cancelled";
6059
+ }
6060
+ async remove(name2, kind = "secret") {
6061
+ await this.#time.sleep(5);
6062
+ const secret = { ...this.#find(name2, kind), state: "removed", removedAt: Date.now() };
6063
+ return this.#flip(secret, "remove");
6064
+ }
6065
+ async restore(name2, kind = "secret") {
6066
+ await this.#time.sleep(5);
6067
+ const { removedAt: _, ...secret } = this.#find(name2, kind);
6068
+ return this.#flip({ ...secret, state: secret.rules.length ? "active" : "inert" }, "restore");
6069
+ }
6070
+ #flip(secret, type) {
6071
+ this.#list = {
6072
+ ...this.#list,
6073
+ secrets: this.#list.secrets.map(
6074
+ (item) => item.name === secret.name && item.kind === secret.kind ? secret : item
6075
+ )
6076
+ };
6077
+ this.#log(secret.name, { type });
5835
6078
  this.emit("list", this.#list);
6079
+ return { name: secret.name, placeholder: secret.placeholder, state: secret.state };
6080
+ }
6081
+ async import(kind, bytes, options = {}) {
6082
+ await this.#time.sleep(5);
6083
+ this.#unlocked();
6084
+ if (kind === "six") throw vaultFailure("ENOTSUP", "six imports are not supported yet.");
6085
+ if (!bytes.length) throw vaultFailure("EINVAL", "The file is empty.");
6086
+ const { pick } = options;
6087
+ this.imports.push({
6088
+ kind,
6089
+ size: bytes.length,
6090
+ password: !!options.password,
6091
+ ...pick ? { pick: [...pick] } : {}
6092
+ });
6093
+ const offered = kind === "keepass" ? [...candidates, duplicate] : candidates;
6094
+ if (!pick) return { stage: "pick", candidates: offered.map((item) => ({ ...item })) };
6095
+ const chosen = new Map(
6096
+ pick.map(
6097
+ (item) => typeof item === "string" ? [item, "secret"] : [item.name, item.kind]
6098
+ )
6099
+ );
6100
+ const taken = offered.filter((item) => chosen.has(item.name) && !item.refused);
6101
+ return {
6102
+ stage: "done",
6103
+ imported: taken.map((item) => this.#seal(item.name, `import:${kind}`, chosen.get(item.name))),
6104
+ skipped: offered.filter((item) => !taken.includes(item)).map((item) => item.name),
6105
+ reasons: Object.fromEntries(
6106
+ offered.flatMap((item) => item.refused ? [[item.name, item.refused]] : [])
6107
+ )
6108
+ };
6109
+ }
6110
+ async export(passphrase) {
6111
+ await this.#time.sleep(5);
6112
+ this.#unlocked();
6113
+ if (new TextEncoder().encode(passphrase).length < 8)
6114
+ throw vaultFailure("EINVAL", "Passphrases need at least 8 bytes.");
6115
+ this.exported += 1;
6116
+ this.#status = { ...this.#status, exportedAt: Date.now(), backupReminder: null };
6117
+ this.emit("status", this.#status);
6118
+ return new TextEncoder().encode("slicc-vault invented bundle");
6119
+ }
6120
+ async lock() {
6121
+ await this.#time.sleep(5);
6122
+ this.#failed();
6123
+ this.#status = { ...this.#status, locked: true };
5836
6124
  this.emit("status", this.#status);
5837
6125
  }
5838
6126
  button() {
@@ -5844,26 +6132,16 @@ var DummyVault = class extends Emitter {
5844
6132
  return this.#status.locked ? "Vault locked" : "Vault unlocked";
5845
6133
  }
5846
6134
  autoIntent() {
5847
- return this.#status.locked ? { kind: "unlock" } : { kind: "manage" };
6135
+ return this.#status.locked ? { kind: "unlock" } : { kind: "protect" };
5848
6136
  }
5849
6137
  async answer(intent) {
5850
6138
  await this.#time.sleep(10);
5851
- if (intent.kind === "unlock") {
5852
- this.#status = { ...this.#status, locked: false };
5853
- this.emit("status", this.#status);
5854
- return null;
5855
- }
5856
- if (intent.kind !== "request" && intent.kind !== "enter") return null;
5857
- const request = this.#status.waiting.find((item) => item.id === intent.request);
5858
- const name2 = intent.kind === "enter" ? intent.name : request?.name ?? "NEW_SECRET";
5859
- this.#status = {
6139
+ this.#status = intent.kind === "unlock" ? {
5860
6140
  ...this.#status,
5861
6141
  locked: false,
5862
- waiting: this.#status.waiting.filter((item) => item !== request)
5863
- };
6142
+ scrub: { needed: false, version: 0, ...this.#status.scrub, ready: true }
6143
+ } : { ...this.#status, lock: "passkey" };
5864
6144
  this.emit("status", this.#status);
5865
- const record = this.#list.secrets.find((secret) => secret.name === name2);
5866
- return { name: name2, placeholder: record?.placeholder ?? "fnox_proxy_new00001", state: "active" };
5867
6145
  }
5868
6146
  };
5869
6147
 
@@ -5983,6 +6261,8 @@ export {
5983
6261
  vaultFixtures,
5984
6262
  vaultNotice,
5985
6263
  vaultOlder,
6264
+ vaultPolicy,
6265
+ vaultRefused,
5986
6266
  vaultSecrets
5987
6267
  };
5988
6268
  //# sourceMappingURL=slicc-dummy.js.map