instar 1.3.1654 → 1.3.1655

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 (35) hide show
  1. package/dashboard/console/allowed.js +1 -1
  2. package/dashboard/console/services-model.js +3 -2
  3. package/dashboard-pair/service-yes.js +22 -7
  4. package/dist/commands/server.d.ts.map +1 -1
  5. package/dist/commands/server.js +13 -0
  6. package/dist/commands/server.js.map +1 -1
  7. package/dist/core/rebalanceProof.d.ts +22 -0
  8. package/dist/core/rebalanceProof.d.ts.map +1 -1
  9. package/dist/core/rebalanceProof.js +44 -5
  10. package/dist/core/rebalanceProof.js.map +1 -1
  11. package/dist/data/standards-guard-index.json +1 -1
  12. package/dist/data/standards-guard-index.meta.json +2 -2
  13. package/dist/data/standards-registry.meta.json +1 -1
  14. package/dist/native/InstarWedgeCanary.app/Contents/MacOS/InstarWedgeCanary +0 -0
  15. package/dist/native/instar-desktop-host +0 -0
  16. package/dist/recommended/confirmTokens.d.ts +5 -0
  17. package/dist/recommended/confirmTokens.d.ts.map +1 -1
  18. package/dist/recommended/confirmTokens.js +10 -0
  19. package/dist/recommended/confirmTokens.js.map +1 -1
  20. package/dist/server/CapabilityIndex.js +1 -1
  21. package/dist/server/CapabilityIndex.js.map +1 -1
  22. package/dist/server/recommendedServiceRoutes.d.ts.map +1 -1
  23. package/dist/server/recommendedServiceRoutes.js +43 -3
  24. package/dist/server/recommendedServiceRoutes.js.map +1 -1
  25. package/dist/server/routes.d.ts.map +1 -1
  26. package/dist/server/routes.js +21 -0
  27. package/dist/server/routes.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/data/builtin-manifest.json +46 -46
  30. package/src/data/standards-guard-index.json +1 -1
  31. package/src/data/standards-guard-index.meta.json +2 -2
  32. package/src/data/standards-registry.meta.json +1 -1
  33. package/upgrades/1.3.1655.md +28 -0
  34. package/upgrades/side-effects/rebalance-proof-via-holder.md +48 -0
  35. package/upgrades/side-effects/recommended-services-no.md +66 -0
@@ -183,7 +183,7 @@ function suggestionsBlock(sg, post, refresh) {
183
183
  // ── Outside services ──────────────────────────────────────────────────────
184
184
  function servicesBlock(services) {
185
185
  if (!services.ok) return el('section', { class: 'list-section', id: 'sec-services' }, el('div', { class: 'list-head' }, el('h2', { class: 'eyebrow', text: 'Outside services' })), cantTell(services.reason));
186
- const wrap = section({ id: 'services', title: 'Outside services', rows: services.rows, onRow: (r) => sheet({ title: r.main }, story(r.lines), r.yesHref ? el('a', { class: 'btn-primary btn-inline', href: r.yesHref, text: 'Set this up' }) : null) });
186
+ const wrap = section({ id: 'services', title: 'Outside services', rows: services.rows, onRow: (r) => sheet({ title: r.main }, story(r.lines), r.action ? el('a', { class: 'btn-primary btn-inline', href: r.action.href, text: r.action.label }) : null) });
187
187
  if (services.note) wrap.querySelector('.list-head').after(note(services.note));
188
188
  return wrap;
189
189
  }
@@ -30,8 +30,9 @@ export function buildServices(res) {
30
30
  main: s.name || s.service,
31
31
  sub: s.benefit || '',
32
32
  end: choiceWord(s),
33
- // Only something that can be set up gets a way to say yes, and a yes already given needs none.
34
- yesHref: s.available && s.choice !== 'yes' ? `/dashboard/service-yes?service=${encodeURIComponent(s.service)}` : null,
33
+ // The same page takes a yes or a no. A yes on another machine, or one a later no cancelled, leaves
34
+ // this machine still needing its own, so the choice alone doesn't decide this.
35
+ action: s.available ? { href: `/dashboard/service-yes?service=${encodeURIComponent(s.service)}`, label: s.grantedHere ? 'Change my answer' : 'Yes or no' } : null,
35
36
  lines: [
36
37
  { label: 'What you get', text: s.benefit },
37
38
  { label: 'What leaves this machine', text: s.dataLeaves },
@@ -14,15 +14,17 @@ const REFUSED = {
14
14
  'insecure-connection': 'This connection isn’t secure enough to take your PIN. Nothing changed. Open this page through your agent’s secure address.',
15
15
  'wrong-owner': 'The owner of this agent changed since this page opened. Nothing changed. Open it again.',
16
16
  'wrong-machine': 'This page belongs to a different machine. Nothing changed. Open it again.',
17
+ 'too-many-pages': 'This page has been opened too many times in a short while. Nothing changed. Wait a minute, then open it again.',
17
18
  'recommended-services-unavailable': 'I can’t save a choice on this machine right now. Nothing changed.',
18
19
  };
19
20
 
21
+ const REASONS = [['none', 'No particular reason'], ['cost', 'The cost'], ['privacy', 'Privacy'], ['not-needed', 'I don’t need it'], ['have-another', 'I use something else'], ['other', 'Something else']];
22
+
20
23
  function el(tag, attrs = {}, ...kids) {
21
24
  const n = document.createElement(tag);
22
25
  for (const [k, v] of Object.entries(attrs)) {
23
26
  if (k === 'text') n.textContent = v;
24
27
  else if (k === 'class') n.className = v;
25
- else if (k === 'onclick') n.addEventListener('click', v);
26
28
  else if (k === 'onsubmit') n.addEventListener('submit', v);
27
29
  else n.setAttribute(k, v);
28
30
  }
@@ -37,18 +39,25 @@ function line(label, text) { return text ? el('section', {}, el('h2', { text: la
37
39
  function page(d) {
38
40
  const error = el('p', { class: 'pair-error', role: 'alert' });
39
41
  const pin = el('input', { type: 'password', inputmode: 'numeric', autocomplete: 'off', 'aria-label': 'Your PIN', placeholder: 'Your PIN' });
40
- const button = el('button', { class: 'pair-button', type: 'submit', text: `Yes, set up ${d.name}` });
41
- const form = el('form', { class: 'pair-pin', onsubmit: async (e) => {
42
- e.preventDefault();
42
+ const button = el('button', { class: 'pair-button', type: 'button', text: `Yes, set up ${d.name}` });
43
+ const reason = el('select', { 'aria-label': 'Why not? This is optional.' },
44
+ ...REASONS.map(([value, text]) => el('option', { value, text })));
45
+ const noButton = el('button', { class: 'pair-link-button', type: 'button', text: `No, don’t set up ${d.name}` });
46
+ const send = async (answer) => {
43
47
  error.textContent = '';
44
48
  button.disabled = true;
49
+ noButton.disabled = true;
45
50
  try {
46
51
  const r = await fetch(`/recommended-services/${encodeURIComponent(service)}/confirm`, {
47
52
  method: 'POST', cache: 'no-store',
48
53
  headers: { 'Content-Type': 'application/json', 'X-Instar-Request': '1' },
49
- body: JSON.stringify({ token: d.token, pin: pin.value }),
54
+ body: JSON.stringify({ token: d.token, pin: pin.value, answer, reason: answer === 'no' ? reason.value : 'none' }),
50
55
  });
51
56
  const body = await r.json().catch(() => ({}));
57
+ if (r.ok && answer === 'no') {
58
+ message('Got it', `I won’t set up ${d.name} or bring it up again, unless a real problem comes up that it would help with, something changes that matters to you, or a long time has passed and there’s good reason to think you’d answer differently. If it’s already running, it stays on until you ask me to stop it.`);
59
+ return;
60
+ }
52
61
  if (r.ok) {
53
62
  message('Thank you', `I’ll set up ${d.name} from here and tell you when it’s working. I’ll only come back to you for a decision or a credential.`);
54
63
  return;
@@ -64,8 +73,13 @@ function page(d) {
64
73
  error.textContent = 'I couldn’t reach your agent. Nothing changed. Try again.';
65
74
  } finally {
66
75
  button.disabled = false;
76
+ noButton.disabled = false;
67
77
  }
68
- } }, pin, error, button);
78
+ };
79
+ noButton.addEventListener('click', () => send('no'));
80
+ button.addEventListener('click', () => send('yes'));
81
+ // Enter does nothing: someone typing their PIN to say no must never record a yes by pressing Go.
82
+ const form = el('form', { class: 'pair-pin', onsubmit: (e) => e.preventDefault() }, pin, error, button);
69
83
  show(
70
84
  el('div', { class: 'pair-head' }, el('h1', { text: `Set up ${d.name}?` })),
71
85
  line('What you get', d.benefit),
@@ -76,7 +90,8 @@ function page(d) {
76
90
  line('If you say no', d.backup || 'There’s no backup yet.'),
77
91
  el('section', {}, el('h2', { text: 'After you say yes' }), el('p', { text: 'Setup is my job. I’ll only ask you for a decision, such as a payment, or a credential.' })),
78
92
  form,
79
- el('p', { class: 'pair-hint', text: 'If you’d rather not, just close this page. Nothing changes.' }),
93
+ el('section', {}, el('h2', { text: 'Or say no' }), el('p', { class: 'pair-hint', text: 'Type your PIN above first. The reason is optional. Saying no stops me setting this up or offering it. If it’s already running, it stays on until you ask me to stop it.' }), reason, noButton),
94
+ el('p', { class: 'pair-hint', text: 'If you’re not sure yet, just close this page. Nothing changes.' }),
80
95
  );
81
96
  }
82
97
 
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAkIA,OAAO,EAAE,cAAc,EAAwD,MAAM,2BAA2B,CAAC;AAgBjH,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AA6BjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA8J7D,OAAO,KAAK,EAAW,oBAAoB,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA4GtD,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AA0ID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA+DD,+EAA+E;AAC/E,wBAAgB,qCAAqC,CACnD,SAAS,EAAE,IAAI,CAAC,OAAO,2BAA2B,EAAE,cAAc,EAAE,QAAQ,CAAC,GAAG,IAAI,EACpF,OAAO,EAAE,MAAM,GACd,IAAI,CAEN;AAqmBD,wBAAsB,oBAAoB,CACxC,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,eAAe,EACzB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,kBAAkB,CAAC,EAAE,MAAM;AAC3B;;qCAEqC;AACrC,WAAW,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE;AACzD;;wEAEwE;AACxE,SAAS,CAAC,EAAE;IACV,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;sEAGkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;4BAIwB;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,OAAO,CAAC,MAAM,CAAC,CAkajB;AA8xBD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,oBAAoB,GAAG,IAAI,GACxC;IACD,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqBA;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAQrD,oBAAoB,CAAC,EAAE,MAAM;IAC3B,YAAY,EAAE,OAAO,kBAAkB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,GACP,IAAI,CA85BN;AAwsBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgp3BtE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDzE;AA+BD,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkE5E"}
@@ -24787,6 +24787,19 @@ export async function startServer(options) {
24787
24787
  return false;
24788
24788
  },
24789
24789
  move: (t, to) => planner.proofMove(String(t), to),
24790
+ probeViaHolder: async (t, nonce) => {
24791
+ const holderUrl = _resolveRouterUrl?.() ?? null;
24792
+ if (!holderUrl)
24793
+ return null;
24794
+ const r = await fetch(`${holderUrl}/session-pool/rebalance-proof/probe`, {
24795
+ method: 'POST',
24796
+ headers: { Authorization: `Bearer ${config.authToken}`, 'Content-Type': 'application/json', 'X-Instar-AgentId': config.projectName },
24797
+ body: JSON.stringify({ topic: t, nonce }),
24798
+ signal: AbortSignal.timeout(30_000),
24799
+ });
24800
+ const j = await r.json().catch(() => ({})); // @silent-fallback-ok: a body we cannot read is reported as the status below
24801
+ return { action: j.action ?? j.refused ?? `holder-status-${r.status}`, holder: j.holder ?? null };
24802
+ },
24790
24803
  sendProbe: async (t, text, messageId) => {
24791
24804
  if (!_sessionRouter)
24792
24805
  return 'no-router';