@integrity-labs/agt-cli 0.28.973 → 0.28.975

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp/index.js CHANGED
@@ -24656,21 +24656,80 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
24656
24656
  // ancestors too - a wider style mutation than intended, for a probe whose
24657
24657
  // result the caller then rejects anyway.
24658
24658
  function textNodeAtPointThrough(x,y,target){
24659
+ return throughOverlays(x,y,target,function(){ return textNodeAtPoint(x,y); });
24660
+ }
24661
+ // Run probe() with everything stacked IN FRONT of target muted for pointer
24662
+ // hit-testing, then restore it. Shared by the text-node probe above and the
24663
+ // caret placement below (ENG-10632), so there is one overlay-muting path.
24664
+ // A target that is not in the hit stack (or no elementsFromPoint at all) runs
24665
+ // the probe unmuted, for the reason given on textNodeAtPointThrough.
24666
+ function throughOverlays(x,y,target,probe){
24659
24667
  var stack;
24660
- try{ stack=document.elementsFromPoint(x,y)||[]; }catch(e){ return textNodeAtPoint(x,y); }
24668
+ try{ stack=document.elementsFromPoint(x,y)||[]; }catch(e){ return probe(); }
24661
24669
  var cut=-1, i;
24662
- for(i=0;i<stack.length;i++){ if(stack[i]===target){ cut=i; break; } }
24663
- if(cut<0) return textNodeAtPoint(x,y);
24670
+ for(i=0;i<stack.length;i++){ if(stack[i]===target || (target && target.contains && stack[i] && stack[i].nodeType && target.contains(stack[i]))){ cut=i; break; } }
24671
+ if(cut<0) return probe();
24664
24672
  var muted=[];
24665
24673
  for(i=0;i<cut;i++){
24666
24674
  muted.push([stack[i], stack[i].style ? stack[i].style.pointerEvents : '']);
24667
24675
  try{ stack[i].style.pointerEvents='none'; }catch(e){}
24668
24676
  }
24669
- try{ return textNodeAtPoint(x,y); }
24677
+ try{ return probe(); }
24670
24678
  finally{
24671
24679
  for(i=0;i<muted.length;i++){ try{ muted[i][0].style.pointerEvents=muted[i][1]||''; }catch(e){} }
24672
24680
  }
24673
24681
  }
24682
+ // ENG-10632: is this pointer event aimed INSIDE the open editor?
24683
+ //
24684
+ // 'direct' - the event's own target is the editor or inside it (no overlay).
24685
+ // 'through' - the target is something laid over the editor (a deck click
24686
+ // zone), but the editor is in the hit stack under the pointer.
24687
+ // null - no edit is open, or the press is genuinely elsewhere.
24688
+ //
24689
+ // WHY NOT e.target ALONE. That is exactly the ENG-8477 blind spot: a pointer
24690
+ // event targets the HIT-TEST result, and a deck's full-viewport zones win the
24691
+ // hit test, so e.target is the zone for every press on slide text. ENG-8477
24692
+ // fixed the click that OPENS an editor this way and left the guards that
24693
+ // protect an OPEN editor keyed on e.target, so the second click - the one that
24694
+ // places the caret - was handed to the zone and paged the slide.
24695
+ //
24696
+ // A keydown is different: it targets the FOCUSED element, so the ENG-8500 key
24697
+ // guard's e.target test is correct and stays as it is.
24698
+ function pointInEditor(e){
24699
+ if(!editing || !e) return null;
24700
+ var t=e.target;
24701
+ if(t===editing || (editing.contains && t && t.nodeType && editing.contains(t))) return 'direct';
24702
+ if(typeof e.clientX!=='number' || typeof e.clientY!=='number') return null;
24703
+ var stack;
24704
+ try{ stack=document.elementsFromPoint(e.clientX, e.clientY)||[]; }catch(err){ return null; }
24705
+ for(var i=0;i<stack.length;i++){
24706
+ var n=stack[i];
24707
+ if(n===editing || (editing.contains && n && n.nodeType && editing.contains(n))) return 'through';
24708
+ }
24709
+ return null;
24710
+ }
24711
+ // ENG-10632: put the caret where the viewer pressed, as the browser would have
24712
+ // if nothing covered the editor. The browser's own caret placement goes to the
24713
+ // topmost element, which is the overlay, so it places nothing in the text.
24714
+ // Returns true when a caret was placed inside the editor.
24715
+ function placeCaretAtPointThrough(x,y,el){
24716
+ return throughOverlays(x,y,el,function(){
24717
+ try{
24718
+ var node=null, offset=0, r=null;
24719
+ if(document.caretRangeFromPoint){
24720
+ r=document.caretRangeFromPoint(x,y);
24721
+ if(r){ node=r.startContainer; offset=r.startOffset||0; }
24722
+ } else if(document.caretPositionFromPoint){
24723
+ var p=document.caretPositionFromPoint(x,y);
24724
+ if(p){ node=p.offsetNode; offset=p.offset||0; }
24725
+ }
24726
+ if(!node || !(node===el || (el.contains && el.contains(node.nodeType===3 ? node.parentNode||node.parentElement : node)))) return false;
24727
+ if(!r){ r=document.createRange(); r.setStart(node, offset); r.collapse(true); }
24728
+ var s=document.getSelection(); s.removeAllRanges(); s.addRange(r);
24729
+ return true;
24730
+ }catch(err){ return false; }
24731
+ });
24732
+ }
24674
24733
  // Index of a text node among its parent's child TEXT nodes, in order - the same
24675
24734
  // counting the server uses to re-locate it in source_html (ENG-6856).
24676
24735
  function textIndexOf(container, tn){
@@ -24678,6 +24737,13 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
24678
24737
  for(var k=0;k<ns.length;k++){ if(ns[k].nodeType===3){ i++; if(ns[k]===tn) return i; } }
24679
24738
  return -1;
24680
24739
  }
24740
+ function keepCaretIn(el){
24741
+ try{
24742
+ var s=document.getSelection(), n=s && s.rangeCount ? s.anchorNode : null;
24743
+ if(n && (n===el || (el.contains && el.contains(n.nodeType===3 ? n.parentNode : n)))) return;
24744
+ }catch(err){}
24745
+ placeCaretEnd(el);
24746
+ }
24681
24747
  function placeCaretEnd(el){ try{ var r=document.createRange(); r.selectNodeContents(el); r.collapse(false); var s=document.getSelection(); s.removeAllRanges(); s.addRange(r); }catch(e){} }
24682
24748
  // The Save/Cancel toolbar anchored above el. Shared by whole-element edits
24683
24749
  // (startEdit) and per-text-node edits (startEditTextNode).
@@ -24887,9 +24953,35 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
24887
24953
  // press that lands inside the editor. A press anywhere else is the viewer
24888
24954
  // leaving, and the artefact keeps it.
24889
24955
  window.addEventListener('pointerdown', function(e){
24890
- if(!editing) return;
24891
- var t=e.target;
24892
- if(t!==editing && !(editing.contains && t && t.nodeType && editing.contains(t))) return;
24956
+ // ENG-10632: "inside the editor" is decided through the hit stack, not from
24957
+ // e.target, which a deck's click zone always wins. See pointInEditor.
24958
+ var where=pointInEditor(e);
24959
+ if(!where) return;
24960
+ e.stopImmediatePropagation();
24961
+ if(where==='through'){
24962
+ // The overlay is the browser's hit target, so its default action would
24963
+ // move focus off the editor and place no caret in the text. Take both over.
24964
+ try{ e.preventDefault(); }catch(err){}
24965
+ try{ editing.focus(); }catch(err){}
24966
+ // The press is suppressed either way, so a probe that cannot resolve a
24967
+ // point inside the editor must not leave it without a caret: keep one the
24968
+ // editor already holds, otherwise put it at the end of the text.
24969
+ if(!placeCaretAtPointThrough(e.clientX, e.clientY, editing)) keepCaretIn(editing);
24970
+ }
24971
+ }, true);
24972
+ // ENG-10632: the same press also arrives as mousedown and click, and the deck
24973
+ // can page on either. Only a press that went THROUGH an overlay into the open
24974
+ // editor is swallowed; a direct press keeps its native behaviour (caret,
24975
+ // drag-select), and a press anywhere else is the viewer leaving and is left to
24976
+ // the artefact.
24977
+ window.addEventListener('mousedown', function(e){
24978
+ if(pointInEditor(e)!=='through') return;
24979
+ try{ e.preventDefault(); }catch(err){}
24980
+ e.stopImmediatePropagation();
24981
+ }, true);
24982
+ window.addEventListener('click', function(e){
24983
+ if(pointInEditor(e)!=='through') return;
24984
+ try{ e.preventDefault(); }catch(err){}
24893
24985
  e.stopImmediatePropagation();
24894
24986
  }, true);
24895
24987
  // ENG-8477: the hover affordance has the same blind spot as the click did -
@@ -30498,11 +30590,18 @@ var FLAG_REGISTRY = [
30498
30590
  },
30499
30591
  {
30500
30592
  key: "ip-allowlist-enforce-admin-debug",
30501
- description: "ENG-10594 - whether the IP allowlist on the admin-debug surface (/admin/debug/*, including the deliberately unauthenticated POST /admin/debug/token that exchanges a tlk_ key) REFUSES, or merely observes. OFF (default) = shadow: every request is still evaluated and logged with verdict=admit or verdict=would-refuse, and nothing is ever rejected. ON = a caller whose platform-attested source address is outside AGT_IP_ALLOWLIST_ADMIN_DEBUG gets a bare 403. THE SSM PARAMETER IS A SECOND LEVER AND BOTH ARE NEEDED: with the list unset this flag does nothing, because an unconfigured allowlist admits everyone by design. Arm in that order - populate the list, read the shadow logs until the would-refuse set is understood, then flip this. Deliberately global (evaluated with an empty context): the middleware runs BEFORE authentication, so there is no verified org to scope by, and taking one from an unverified request would let a caller choose its own enforcement posture. Separate from the mcp flag on purpose - see that entry.",
30593
+ description: "ENG-10594 - whether the IP allowlist on the admin-debug surface (/admin/debug/*, including the deliberately unauthenticated POST /admin/debug/token that exchanges a tlk_ key) REFUSES, or merely observes. OFF (default) = shadow: every request is still evaluated and logged with verdict=admit or verdict=would-refuse, and nothing is ever rejected. ON = a caller whose platform-attested source address is outside AGT_IP_ALLOWLIST_ADMIN_DEBUG gets a bare 403. THE SSM PARAMETER IS A SECOND LEVER AND BOTH ARE NEEDED: with the list unset this flag does nothing, because an unconfigured allowlist admits everyone by design. Arm in that order - populate the list, read the shadow logs until the would-refuse set is understood, then flip this. Deliberately global (evaluated with an empty context): the middleware runs BEFORE authentication, so there is no verified org to scope by, and taking one from an unverified request would let a caller choose its own enforcement posture. There is deliberately NO counterpart flag for the per-agent MCP surface: that one is shadow-only structurally (its ENFORCE_FLAG entry is null), so arming this one does not and cannot arm that one. See the comment below this entry for why.",
30502
30594
  flagType: "boolean",
30503
- // Shadow. The measurement comes first: nobody yet knows the real set of
30504
- // staff addresses, and arming against a guess locks you out of the very
30505
- // tool you would use to diagnose the lockout.
30595
+ // Shadow. The measurement comes first - and ENG-10664 corrected what the
30596
+ // measurement is OF. This comment used to say "nobody yet knows the real set
30597
+ // of staff addresses": there is no such set. Measured over 48h, all 315
30598
+ // requests to this surface came from ONE address, the agt-hosts AZ-2a NAT
30599
+ // EIP - an AGENT calling the debug_* tools, not a person. The decided policy
30600
+ // is that it stays that way (admin-debug is only ever reached from our own
30601
+ // NAT gateways). So the pre-arm check is not "does my laptop appear" but
30602
+ // "is every NAT EIP in the list", because an AZ whose NAT has not yet
30603
+ // carried a debug_* call is absent from the log and would be refused the
30604
+ // instant this flips. See docs/runbooks/ip-allowlist-rollout.md step 3.
30506
30605
  defaultValue: false,
30507
30606
  // Arming it changes who can reach production diagnostics. Worth one
30508
30607
  // confirmation.
@@ -30517,20 +30616,34 @@ var FLAG_REGISTRY = [
30517
30616
  // ENFORCE_FLAG (packages/api/src/middleware/ip-allowlist.ts) is null, so no
30518
30617
  // flag is consulted and no flag flip can arm it.
30519
30618
  //
30520
- // Why it is not simply a second flag defaulting false: most of that surface's
30521
- // callers have no allowlistable address at all. Per ADR-0032 only hosts in the
30522
- // agt-hosts account egress through stable NAT EIPs; a host with
30523
- // provision_source `self` or `customer-ec2`, or any BYO account, egresses from
30524
- // an address the control plane cannot know. Arming against that population
30525
- // black-holes a customer's whole fleet, and per
30526
- // docs/runbooks/composio-allowlist-rollout.md this class of change has no
30619
+ // Why it is not simply a second flag defaulting false (CORRECTED, ENG-10664):
30620
+ //
30621
+ // This comment used to say the callers are agent HOSTS, most of which have no
30622
+ // allowlistable address per ADR-0032. That is the wrong caller. Agent hosts do
30623
+ // not call this surface at all: its handler's first act is
30624
+ // validateMcpAccessToken() against `mcp_oauth_tokens` (routes/mcp.ts:87, token
30625
+ // check at :91), so a host JWT is rejected outright - routes/host-runtime.ts
30626
+ // :33421 says so in as many words, which is why the ENG-4724 /host/* twins
30627
+ // exist. The caller set is remote MCP OAuth clients, structurally.
30628
+ //
30629
+ // The conclusion is unchanged and ONLY the reason has moved. Allowlisting this
30630
+ // surface would mean pinning a THIRD PARTY's egress ranges rather than our own
30631
+ // NAT EIPs - a different control, a different owner, a different failure mode:
30632
+ // they move a range and agent MCP access breaks with no signal on our side.
30633
+ // Per docs/runbooks/composio-allowlist-rollout.md this class of change has no
30527
30634
  // fleet-level undo. A flag would leave that one toggle away during an
30528
30635
  // incident, from someone who had just armed the admin-debug surface and
30529
30636
  // reasonably assumed the pair moved together. Requiring a code change puts
30530
30637
  // review in front of an irreversible action, which is the right price.
30531
30638
  //
30532
- // If the shadow data ever shows the population IS allowlistable, adding the
30533
- // flag here and a key in ENFORCE_FLAG is a small, deliberate diff.
30639
+ // Keeping the false rationale would have been worse than having none: a reader
30640
+ // who checked it would find it does not hold and might "fix" it by adding the
30641
+ // flag. That is the failure this rewrite exists to prevent.
30642
+ //
30643
+ // If we ever DECIDE to take on that third-party dependency deliberately,
30644
+ // adding the flag here and a key in ENFORCE_FLAG is a small diff - but it is a
30645
+ // decision to own someone else's egress, not a discovery that the population
30646
+ // was allowlistable all along.
30534
30647
  ];
30535
30648
  var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
30536
30649
 
@@ -38807,21 +38807,80 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
38807
38807
  // ancestors too - a wider style mutation than intended, for a probe whose
38808
38808
  // result the caller then rejects anyway.
38809
38809
  function textNodeAtPointThrough(x,y,target){
38810
+ return throughOverlays(x,y,target,function(){ return textNodeAtPoint(x,y); });
38811
+ }
38812
+ // Run probe() with everything stacked IN FRONT of target muted for pointer
38813
+ // hit-testing, then restore it. Shared by the text-node probe above and the
38814
+ // caret placement below (ENG-10632), so there is one overlay-muting path.
38815
+ // A target that is not in the hit stack (or no elementsFromPoint at all) runs
38816
+ // the probe unmuted, for the reason given on textNodeAtPointThrough.
38817
+ function throughOverlays(x,y,target,probe){
38810
38818
  var stack;
38811
- try{ stack=document.elementsFromPoint(x,y)||[]; }catch(e){ return textNodeAtPoint(x,y); }
38819
+ try{ stack=document.elementsFromPoint(x,y)||[]; }catch(e){ return probe(); }
38812
38820
  var cut=-1, i;
38813
- for(i=0;i<stack.length;i++){ if(stack[i]===target){ cut=i; break; } }
38814
- if(cut<0) return textNodeAtPoint(x,y);
38821
+ for(i=0;i<stack.length;i++){ if(stack[i]===target || (target && target.contains && stack[i] && stack[i].nodeType && target.contains(stack[i]))){ cut=i; break; } }
38822
+ if(cut<0) return probe();
38815
38823
  var muted=[];
38816
38824
  for(i=0;i<cut;i++){
38817
38825
  muted.push([stack[i], stack[i].style ? stack[i].style.pointerEvents : '']);
38818
38826
  try{ stack[i].style.pointerEvents='none'; }catch(e){}
38819
38827
  }
38820
- try{ return textNodeAtPoint(x,y); }
38828
+ try{ return probe(); }
38821
38829
  finally{
38822
38830
  for(i=0;i<muted.length;i++){ try{ muted[i][0].style.pointerEvents=muted[i][1]||''; }catch(e){} }
38823
38831
  }
38824
38832
  }
38833
+ // ENG-10632: is this pointer event aimed INSIDE the open editor?
38834
+ //
38835
+ // 'direct' - the event's own target is the editor or inside it (no overlay).
38836
+ // 'through' - the target is something laid over the editor (a deck click
38837
+ // zone), but the editor is in the hit stack under the pointer.
38838
+ // null - no edit is open, or the press is genuinely elsewhere.
38839
+ //
38840
+ // WHY NOT e.target ALONE. That is exactly the ENG-8477 blind spot: a pointer
38841
+ // event targets the HIT-TEST result, and a deck's full-viewport zones win the
38842
+ // hit test, so e.target is the zone for every press on slide text. ENG-8477
38843
+ // fixed the click that OPENS an editor this way and left the guards that
38844
+ // protect an OPEN editor keyed on e.target, so the second click - the one that
38845
+ // places the caret - was handed to the zone and paged the slide.
38846
+ //
38847
+ // A keydown is different: it targets the FOCUSED element, so the ENG-8500 key
38848
+ // guard's e.target test is correct and stays as it is.
38849
+ function pointInEditor(e){
38850
+ if(!editing || !e) return null;
38851
+ var t=e.target;
38852
+ if(t===editing || (editing.contains && t && t.nodeType && editing.contains(t))) return 'direct';
38853
+ if(typeof e.clientX!=='number' || typeof e.clientY!=='number') return null;
38854
+ var stack;
38855
+ try{ stack=document.elementsFromPoint(e.clientX, e.clientY)||[]; }catch(err){ return null; }
38856
+ for(var i=0;i<stack.length;i++){
38857
+ var n=stack[i];
38858
+ if(n===editing || (editing.contains && n && n.nodeType && editing.contains(n))) return 'through';
38859
+ }
38860
+ return null;
38861
+ }
38862
+ // ENG-10632: put the caret where the viewer pressed, as the browser would have
38863
+ // if nothing covered the editor. The browser's own caret placement goes to the
38864
+ // topmost element, which is the overlay, so it places nothing in the text.
38865
+ // Returns true when a caret was placed inside the editor.
38866
+ function placeCaretAtPointThrough(x,y,el){
38867
+ return throughOverlays(x,y,el,function(){
38868
+ try{
38869
+ var node=null, offset=0, r=null;
38870
+ if(document.caretRangeFromPoint){
38871
+ r=document.caretRangeFromPoint(x,y);
38872
+ if(r){ node=r.startContainer; offset=r.startOffset||0; }
38873
+ } else if(document.caretPositionFromPoint){
38874
+ var p=document.caretPositionFromPoint(x,y);
38875
+ if(p){ node=p.offsetNode; offset=p.offset||0; }
38876
+ }
38877
+ if(!node || !(node===el || (el.contains && el.contains(node.nodeType===3 ? node.parentNode||node.parentElement : node)))) return false;
38878
+ if(!r){ r=document.createRange(); r.setStart(node, offset); r.collapse(true); }
38879
+ var s=document.getSelection(); s.removeAllRanges(); s.addRange(r);
38880
+ return true;
38881
+ }catch(err){ return false; }
38882
+ });
38883
+ }
38825
38884
  // Index of a text node among its parent's child TEXT nodes, in order - the same
38826
38885
  // counting the server uses to re-locate it in source_html (ENG-6856).
38827
38886
  function textIndexOf(container, tn){
@@ -38829,6 +38888,13 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
38829
38888
  for(var k=0;k<ns.length;k++){ if(ns[k].nodeType===3){ i++; if(ns[k]===tn) return i; } }
38830
38889
  return -1;
38831
38890
  }
38891
+ function keepCaretIn(el){
38892
+ try{
38893
+ var s=document.getSelection(), n=s && s.rangeCount ? s.anchorNode : null;
38894
+ if(n && (n===el || (el.contains && el.contains(n.nodeType===3 ? n.parentNode : n)))) return;
38895
+ }catch(err){}
38896
+ placeCaretEnd(el);
38897
+ }
38832
38898
  function placeCaretEnd(el){ try{ var r=document.createRange(); r.selectNodeContents(el); r.collapse(false); var s=document.getSelection(); s.removeAllRanges(); s.addRange(r); }catch(e){} }
38833
38899
  // The Save/Cancel toolbar anchored above el. Shared by whole-element edits
38834
38900
  // (startEdit) and per-text-node edits (startEditTextNode).
@@ -39038,9 +39104,35 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
39038
39104
  // press that lands inside the editor. A press anywhere else is the viewer
39039
39105
  // leaving, and the artefact keeps it.
39040
39106
  window.addEventListener('pointerdown', function(e){
39041
- if(!editing) return;
39042
- var t=e.target;
39043
- if(t!==editing && !(editing.contains && t && t.nodeType && editing.contains(t))) return;
39107
+ // ENG-10632: "inside the editor" is decided through the hit stack, not from
39108
+ // e.target, which a deck's click zone always wins. See pointInEditor.
39109
+ var where=pointInEditor(e);
39110
+ if(!where) return;
39111
+ e.stopImmediatePropagation();
39112
+ if(where==='through'){
39113
+ // The overlay is the browser's hit target, so its default action would
39114
+ // move focus off the editor and place no caret in the text. Take both over.
39115
+ try{ e.preventDefault(); }catch(err){}
39116
+ try{ editing.focus(); }catch(err){}
39117
+ // The press is suppressed either way, so a probe that cannot resolve a
39118
+ // point inside the editor must not leave it without a caret: keep one the
39119
+ // editor already holds, otherwise put it at the end of the text.
39120
+ if(!placeCaretAtPointThrough(e.clientX, e.clientY, editing)) keepCaretIn(editing);
39121
+ }
39122
+ }, true);
39123
+ // ENG-10632: the same press also arrives as mousedown and click, and the deck
39124
+ // can page on either. Only a press that went THROUGH an overlay into the open
39125
+ // editor is swallowed; a direct press keeps its native behaviour (caret,
39126
+ // drag-select), and a press anywhere else is the viewer leaving and is left to
39127
+ // the artefact.
39128
+ window.addEventListener('mousedown', function(e){
39129
+ if(pointInEditor(e)!=='through') return;
39130
+ try{ e.preventDefault(); }catch(err){}
39131
+ e.stopImmediatePropagation();
39132
+ }, true);
39133
+ window.addEventListener('click', function(e){
39134
+ if(pointInEditor(e)!=='through') return;
39135
+ try{ e.preventDefault(); }catch(err){}
39044
39136
  e.stopImmediatePropagation();
39045
39137
  }, true);
39046
39138
  // ENG-8477: the hover affordance has the same blind spot as the click did -
@@ -44446,11 +44538,18 @@ var FLAG_REGISTRY = [
44446
44538
  },
44447
44539
  {
44448
44540
  key: "ip-allowlist-enforce-admin-debug",
44449
- description: "ENG-10594 - whether the IP allowlist on the admin-debug surface (/admin/debug/*, including the deliberately unauthenticated POST /admin/debug/token that exchanges a tlk_ key) REFUSES, or merely observes. OFF (default) = shadow: every request is still evaluated and logged with verdict=admit or verdict=would-refuse, and nothing is ever rejected. ON = a caller whose platform-attested source address is outside AGT_IP_ALLOWLIST_ADMIN_DEBUG gets a bare 403. THE SSM PARAMETER IS A SECOND LEVER AND BOTH ARE NEEDED: with the list unset this flag does nothing, because an unconfigured allowlist admits everyone by design. Arm in that order - populate the list, read the shadow logs until the would-refuse set is understood, then flip this. Deliberately global (evaluated with an empty context): the middleware runs BEFORE authentication, so there is no verified org to scope by, and taking one from an unverified request would let a caller choose its own enforcement posture. Separate from the mcp flag on purpose - see that entry.",
44541
+ description: "ENG-10594 - whether the IP allowlist on the admin-debug surface (/admin/debug/*, including the deliberately unauthenticated POST /admin/debug/token that exchanges a tlk_ key) REFUSES, or merely observes. OFF (default) = shadow: every request is still evaluated and logged with verdict=admit or verdict=would-refuse, and nothing is ever rejected. ON = a caller whose platform-attested source address is outside AGT_IP_ALLOWLIST_ADMIN_DEBUG gets a bare 403. THE SSM PARAMETER IS A SECOND LEVER AND BOTH ARE NEEDED: with the list unset this flag does nothing, because an unconfigured allowlist admits everyone by design. Arm in that order - populate the list, read the shadow logs until the would-refuse set is understood, then flip this. Deliberately global (evaluated with an empty context): the middleware runs BEFORE authentication, so there is no verified org to scope by, and taking one from an unverified request would let a caller choose its own enforcement posture. There is deliberately NO counterpart flag for the per-agent MCP surface: that one is shadow-only structurally (its ENFORCE_FLAG entry is null), so arming this one does not and cannot arm that one. See the comment below this entry for why.",
44450
44542
  flagType: "boolean",
44451
- // Shadow. The measurement comes first: nobody yet knows the real set of
44452
- // staff addresses, and arming against a guess locks you out of the very
44453
- // tool you would use to diagnose the lockout.
44543
+ // Shadow. The measurement comes first - and ENG-10664 corrected what the
44544
+ // measurement is OF. This comment used to say "nobody yet knows the real set
44545
+ // of staff addresses": there is no such set. Measured over 48h, all 315
44546
+ // requests to this surface came from ONE address, the agt-hosts AZ-2a NAT
44547
+ // EIP - an AGENT calling the debug_* tools, not a person. The decided policy
44548
+ // is that it stays that way (admin-debug is only ever reached from our own
44549
+ // NAT gateways). So the pre-arm check is not "does my laptop appear" but
44550
+ // "is every NAT EIP in the list", because an AZ whose NAT has not yet
44551
+ // carried a debug_* call is absent from the log and would be refused the
44552
+ // instant this flips. See docs/runbooks/ip-allowlist-rollout.md step 3.
44454
44553
  defaultValue: false,
44455
44554
  // Arming it changes who can reach production diagnostics. Worth one
44456
44555
  // confirmation.
@@ -44465,20 +44564,34 @@ var FLAG_REGISTRY = [
44465
44564
  // ENFORCE_FLAG (packages/api/src/middleware/ip-allowlist.ts) is null, so no
44466
44565
  // flag is consulted and no flag flip can arm it.
44467
44566
  //
44468
- // Why it is not simply a second flag defaulting false: most of that surface's
44469
- // callers have no allowlistable address at all. Per ADR-0032 only hosts in the
44470
- // agt-hosts account egress through stable NAT EIPs; a host with
44471
- // provision_source `self` or `customer-ec2`, or any BYO account, egresses from
44472
- // an address the control plane cannot know. Arming against that population
44473
- // black-holes a customer's whole fleet, and per
44474
- // docs/runbooks/composio-allowlist-rollout.md this class of change has no
44567
+ // Why it is not simply a second flag defaulting false (CORRECTED, ENG-10664):
44568
+ //
44569
+ // This comment used to say the callers are agent HOSTS, most of which have no
44570
+ // allowlistable address per ADR-0032. That is the wrong caller. Agent hosts do
44571
+ // not call this surface at all: its handler's first act is
44572
+ // validateMcpAccessToken() against `mcp_oauth_tokens` (routes/mcp.ts:87, token
44573
+ // check at :91), so a host JWT is rejected outright - routes/host-runtime.ts
44574
+ // :33421 says so in as many words, which is why the ENG-4724 /host/* twins
44575
+ // exist. The caller set is remote MCP OAuth clients, structurally.
44576
+ //
44577
+ // The conclusion is unchanged and ONLY the reason has moved. Allowlisting this
44578
+ // surface would mean pinning a THIRD PARTY's egress ranges rather than our own
44579
+ // NAT EIPs - a different control, a different owner, a different failure mode:
44580
+ // they move a range and agent MCP access breaks with no signal on our side.
44581
+ // Per docs/runbooks/composio-allowlist-rollout.md this class of change has no
44475
44582
  // fleet-level undo. A flag would leave that one toggle away during an
44476
44583
  // incident, from someone who had just armed the admin-debug surface and
44477
44584
  // reasonably assumed the pair moved together. Requiring a code change puts
44478
44585
  // review in front of an irreversible action, which is the right price.
44479
44586
  //
44480
- // If the shadow data ever shows the population IS allowlistable, adding the
44481
- // flag here and a key in ENFORCE_FLAG is a small, deliberate diff.
44587
+ // Keeping the false rationale would have been worse than having none: a reader
44588
+ // who checked it would find it does not hold and might "fix" it by adding the
44589
+ // flag. That is the failure this rewrite exists to prevent.
44590
+ //
44591
+ // If we ever DECIDE to take on that third-party dependency deliberately,
44592
+ // adding the flag here and a key in ENFORCE_FLAG is a small diff - but it is a
44593
+ // decision to own someone else's egress, not a discovery that the population
44594
+ // was allowlistable all along.
44482
44595
  ];
44483
44596
  var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
44484
44597
 
@@ -33024,21 +33024,80 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
33024
33024
  // ancestors too - a wider style mutation than intended, for a probe whose
33025
33025
  // result the caller then rejects anyway.
33026
33026
  function textNodeAtPointThrough(x,y,target){
33027
+ return throughOverlays(x,y,target,function(){ return textNodeAtPoint(x,y); });
33028
+ }
33029
+ // Run probe() with everything stacked IN FRONT of target muted for pointer
33030
+ // hit-testing, then restore it. Shared by the text-node probe above and the
33031
+ // caret placement below (ENG-10632), so there is one overlay-muting path.
33032
+ // A target that is not in the hit stack (or no elementsFromPoint at all) runs
33033
+ // the probe unmuted, for the reason given on textNodeAtPointThrough.
33034
+ function throughOverlays(x,y,target,probe){
33027
33035
  var stack;
33028
- try{ stack=document.elementsFromPoint(x,y)||[]; }catch(e){ return textNodeAtPoint(x,y); }
33036
+ try{ stack=document.elementsFromPoint(x,y)||[]; }catch(e){ return probe(); }
33029
33037
  var cut=-1, i;
33030
- for(i=0;i<stack.length;i++){ if(stack[i]===target){ cut=i; break; } }
33031
- if(cut<0) return textNodeAtPoint(x,y);
33038
+ for(i=0;i<stack.length;i++){ if(stack[i]===target || (target && target.contains && stack[i] && stack[i].nodeType && target.contains(stack[i]))){ cut=i; break; } }
33039
+ if(cut<0) return probe();
33032
33040
  var muted=[];
33033
33041
  for(i=0;i<cut;i++){
33034
33042
  muted.push([stack[i], stack[i].style ? stack[i].style.pointerEvents : '']);
33035
33043
  try{ stack[i].style.pointerEvents='none'; }catch(e){}
33036
33044
  }
33037
- try{ return textNodeAtPoint(x,y); }
33045
+ try{ return probe(); }
33038
33046
  finally{
33039
33047
  for(i=0;i<muted.length;i++){ try{ muted[i][0].style.pointerEvents=muted[i][1]||''; }catch(e){} }
33040
33048
  }
33041
33049
  }
33050
+ // ENG-10632: is this pointer event aimed INSIDE the open editor?
33051
+ //
33052
+ // 'direct' - the event's own target is the editor or inside it (no overlay).
33053
+ // 'through' - the target is something laid over the editor (a deck click
33054
+ // zone), but the editor is in the hit stack under the pointer.
33055
+ // null - no edit is open, or the press is genuinely elsewhere.
33056
+ //
33057
+ // WHY NOT e.target ALONE. That is exactly the ENG-8477 blind spot: a pointer
33058
+ // event targets the HIT-TEST result, and a deck's full-viewport zones win the
33059
+ // hit test, so e.target is the zone for every press on slide text. ENG-8477
33060
+ // fixed the click that OPENS an editor this way and left the guards that
33061
+ // protect an OPEN editor keyed on e.target, so the second click - the one that
33062
+ // places the caret - was handed to the zone and paged the slide.
33063
+ //
33064
+ // A keydown is different: it targets the FOCUSED element, so the ENG-8500 key
33065
+ // guard's e.target test is correct and stays as it is.
33066
+ function pointInEditor(e){
33067
+ if(!editing || !e) return null;
33068
+ var t=e.target;
33069
+ if(t===editing || (editing.contains && t && t.nodeType && editing.contains(t))) return 'direct';
33070
+ if(typeof e.clientX!=='number' || typeof e.clientY!=='number') return null;
33071
+ var stack;
33072
+ try{ stack=document.elementsFromPoint(e.clientX, e.clientY)||[]; }catch(err){ return null; }
33073
+ for(var i=0;i<stack.length;i++){
33074
+ var n=stack[i];
33075
+ if(n===editing || (editing.contains && n && n.nodeType && editing.contains(n))) return 'through';
33076
+ }
33077
+ return null;
33078
+ }
33079
+ // ENG-10632: put the caret where the viewer pressed, as the browser would have
33080
+ // if nothing covered the editor. The browser's own caret placement goes to the
33081
+ // topmost element, which is the overlay, so it places nothing in the text.
33082
+ // Returns true when a caret was placed inside the editor.
33083
+ function placeCaretAtPointThrough(x,y,el){
33084
+ return throughOverlays(x,y,el,function(){
33085
+ try{
33086
+ var node=null, offset=0, r=null;
33087
+ if(document.caretRangeFromPoint){
33088
+ r=document.caretRangeFromPoint(x,y);
33089
+ if(r){ node=r.startContainer; offset=r.startOffset||0; }
33090
+ } else if(document.caretPositionFromPoint){
33091
+ var p=document.caretPositionFromPoint(x,y);
33092
+ if(p){ node=p.offsetNode; offset=p.offset||0; }
33093
+ }
33094
+ if(!node || !(node===el || (el.contains && el.contains(node.nodeType===3 ? node.parentNode||node.parentElement : node)))) return false;
33095
+ if(!r){ r=document.createRange(); r.setStart(node, offset); r.collapse(true); }
33096
+ var s=document.getSelection(); s.removeAllRanges(); s.addRange(r);
33097
+ return true;
33098
+ }catch(err){ return false; }
33099
+ });
33100
+ }
33042
33101
  // Index of a text node among its parent's child TEXT nodes, in order - the same
33043
33102
  // counting the server uses to re-locate it in source_html (ENG-6856).
33044
33103
  function textIndexOf(container, tn){
@@ -33046,6 +33105,13 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
33046
33105
  for(var k=0;k<ns.length;k++){ if(ns[k].nodeType===3){ i++; if(ns[k]===tn) return i; } }
33047
33106
  return -1;
33048
33107
  }
33108
+ function keepCaretIn(el){
33109
+ try{
33110
+ var s=document.getSelection(), n=s && s.rangeCount ? s.anchorNode : null;
33111
+ if(n && (n===el || (el.contains && el.contains(n.nodeType===3 ? n.parentNode : n)))) return;
33112
+ }catch(err){}
33113
+ placeCaretEnd(el);
33114
+ }
33049
33115
  function placeCaretEnd(el){ try{ var r=document.createRange(); r.selectNodeContents(el); r.collapse(false); var s=document.getSelection(); s.removeAllRanges(); s.addRange(r); }catch(e){} }
33050
33116
  // The Save/Cancel toolbar anchored above el. Shared by whole-element edits
33051
33117
  // (startEdit) and per-text-node edits (startEditTextNode).
@@ -33255,9 +33321,35 @@ var MARKUP_BRIDGE_SCRIPT = `<script>(function(){
33255
33321
  // press that lands inside the editor. A press anywhere else is the viewer
33256
33322
  // leaving, and the artefact keeps it.
33257
33323
  window.addEventListener('pointerdown', function(e){
33258
- if(!editing) return;
33259
- var t=e.target;
33260
- if(t!==editing && !(editing.contains && t && t.nodeType && editing.contains(t))) return;
33324
+ // ENG-10632: "inside the editor" is decided through the hit stack, not from
33325
+ // e.target, which a deck's click zone always wins. See pointInEditor.
33326
+ var where=pointInEditor(e);
33327
+ if(!where) return;
33328
+ e.stopImmediatePropagation();
33329
+ if(where==='through'){
33330
+ // The overlay is the browser's hit target, so its default action would
33331
+ // move focus off the editor and place no caret in the text. Take both over.
33332
+ try{ e.preventDefault(); }catch(err){}
33333
+ try{ editing.focus(); }catch(err){}
33334
+ // The press is suppressed either way, so a probe that cannot resolve a
33335
+ // point inside the editor must not leave it without a caret: keep one the
33336
+ // editor already holds, otherwise put it at the end of the text.
33337
+ if(!placeCaretAtPointThrough(e.clientX, e.clientY, editing)) keepCaretIn(editing);
33338
+ }
33339
+ }, true);
33340
+ // ENG-10632: the same press also arrives as mousedown and click, and the deck
33341
+ // can page on either. Only a press that went THROUGH an overlay into the open
33342
+ // editor is swallowed; a direct press keeps its native behaviour (caret,
33343
+ // drag-select), and a press anywhere else is the viewer leaving and is left to
33344
+ // the artefact.
33345
+ window.addEventListener('mousedown', function(e){
33346
+ if(pointInEditor(e)!=='through') return;
33347
+ try{ e.preventDefault(); }catch(err){}
33348
+ e.stopImmediatePropagation();
33349
+ }, true);
33350
+ window.addEventListener('click', function(e){
33351
+ if(pointInEditor(e)!=='through') return;
33352
+ try{ e.preventDefault(); }catch(err){}
33261
33353
  e.stopImmediatePropagation();
33262
33354
  }, true);
33263
33355
  // ENG-8477: the hover affordance has the same blind spot as the click did -
@@ -39085,11 +39177,18 @@ var FLAG_REGISTRY = [
39085
39177
  },
39086
39178
  {
39087
39179
  key: "ip-allowlist-enforce-admin-debug",
39088
- description: "ENG-10594 - whether the IP allowlist on the admin-debug surface (/admin/debug/*, including the deliberately unauthenticated POST /admin/debug/token that exchanges a tlk_ key) REFUSES, or merely observes. OFF (default) = shadow: every request is still evaluated and logged with verdict=admit or verdict=would-refuse, and nothing is ever rejected. ON = a caller whose platform-attested source address is outside AGT_IP_ALLOWLIST_ADMIN_DEBUG gets a bare 403. THE SSM PARAMETER IS A SECOND LEVER AND BOTH ARE NEEDED: with the list unset this flag does nothing, because an unconfigured allowlist admits everyone by design. Arm in that order - populate the list, read the shadow logs until the would-refuse set is understood, then flip this. Deliberately global (evaluated with an empty context): the middleware runs BEFORE authentication, so there is no verified org to scope by, and taking one from an unverified request would let a caller choose its own enforcement posture. Separate from the mcp flag on purpose - see that entry.",
39180
+ description: "ENG-10594 - whether the IP allowlist on the admin-debug surface (/admin/debug/*, including the deliberately unauthenticated POST /admin/debug/token that exchanges a tlk_ key) REFUSES, or merely observes. OFF (default) = shadow: every request is still evaluated and logged with verdict=admit or verdict=would-refuse, and nothing is ever rejected. ON = a caller whose platform-attested source address is outside AGT_IP_ALLOWLIST_ADMIN_DEBUG gets a bare 403. THE SSM PARAMETER IS A SECOND LEVER AND BOTH ARE NEEDED: with the list unset this flag does nothing, because an unconfigured allowlist admits everyone by design. Arm in that order - populate the list, read the shadow logs until the would-refuse set is understood, then flip this. Deliberately global (evaluated with an empty context): the middleware runs BEFORE authentication, so there is no verified org to scope by, and taking one from an unverified request would let a caller choose its own enforcement posture. There is deliberately NO counterpart flag for the per-agent MCP surface: that one is shadow-only structurally (its ENFORCE_FLAG entry is null), so arming this one does not and cannot arm that one. See the comment below this entry for why.",
39089
39181
  flagType: "boolean",
39090
- // Shadow. The measurement comes first: nobody yet knows the real set of
39091
- // staff addresses, and arming against a guess locks you out of the very
39092
- // tool you would use to diagnose the lockout.
39182
+ // Shadow. The measurement comes first - and ENG-10664 corrected what the
39183
+ // measurement is OF. This comment used to say "nobody yet knows the real set
39184
+ // of staff addresses": there is no such set. Measured over 48h, all 315
39185
+ // requests to this surface came from ONE address, the agt-hosts AZ-2a NAT
39186
+ // EIP - an AGENT calling the debug_* tools, not a person. The decided policy
39187
+ // is that it stays that way (admin-debug is only ever reached from our own
39188
+ // NAT gateways). So the pre-arm check is not "does my laptop appear" but
39189
+ // "is every NAT EIP in the list", because an AZ whose NAT has not yet
39190
+ // carried a debug_* call is absent from the log and would be refused the
39191
+ // instant this flips. See docs/runbooks/ip-allowlist-rollout.md step 3.
39093
39192
  defaultValue: false,
39094
39193
  // Arming it changes who can reach production diagnostics. Worth one
39095
39194
  // confirmation.
@@ -39104,20 +39203,34 @@ var FLAG_REGISTRY = [
39104
39203
  // ENFORCE_FLAG (packages/api/src/middleware/ip-allowlist.ts) is null, so no
39105
39204
  // flag is consulted and no flag flip can arm it.
39106
39205
  //
39107
- // Why it is not simply a second flag defaulting false: most of that surface's
39108
- // callers have no allowlistable address at all. Per ADR-0032 only hosts in the
39109
- // agt-hosts account egress through stable NAT EIPs; a host with
39110
- // provision_source `self` or `customer-ec2`, or any BYO account, egresses from
39111
- // an address the control plane cannot know. Arming against that population
39112
- // black-holes a customer's whole fleet, and per
39113
- // docs/runbooks/composio-allowlist-rollout.md this class of change has no
39206
+ // Why it is not simply a second flag defaulting false (CORRECTED, ENG-10664):
39207
+ //
39208
+ // This comment used to say the callers are agent HOSTS, most of which have no
39209
+ // allowlistable address per ADR-0032. That is the wrong caller. Agent hosts do
39210
+ // not call this surface at all: its handler's first act is
39211
+ // validateMcpAccessToken() against `mcp_oauth_tokens` (routes/mcp.ts:87, token
39212
+ // check at :91), so a host JWT is rejected outright - routes/host-runtime.ts
39213
+ // :33421 says so in as many words, which is why the ENG-4724 /host/* twins
39214
+ // exist. The caller set is remote MCP OAuth clients, structurally.
39215
+ //
39216
+ // The conclusion is unchanged and ONLY the reason has moved. Allowlisting this
39217
+ // surface would mean pinning a THIRD PARTY's egress ranges rather than our own
39218
+ // NAT EIPs - a different control, a different owner, a different failure mode:
39219
+ // they move a range and agent MCP access breaks with no signal on our side.
39220
+ // Per docs/runbooks/composio-allowlist-rollout.md this class of change has no
39114
39221
  // fleet-level undo. A flag would leave that one toggle away during an
39115
39222
  // incident, from someone who had just armed the admin-debug surface and
39116
39223
  // reasonably assumed the pair moved together. Requiring a code change puts
39117
39224
  // review in front of an irreversible action, which is the right price.
39118
39225
  //
39119
- // If the shadow data ever shows the population IS allowlistable, adding the
39120
- // flag here and a key in ENFORCE_FLAG is a small, deliberate diff.
39226
+ // Keeping the false rationale would have been worse than having none: a reader
39227
+ // who checked it would find it does not hold and might "fix" it by adding the
39228
+ // flag. That is the failure this rewrite exists to prevent.
39229
+ //
39230
+ // If we ever DECIDE to take on that third-party dependency deliberately,
39231
+ // adding the flag here and a key in ENFORCE_FLAG is a small diff - but it is a
39232
+ // decision to own someone else's egress, not a discovery that the population
39233
+ // was allowlistable all along.
39121
39234
  ];
39122
39235
  var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
39123
39236