"Host list가 그냥 설정처럼 보였는데 주소 하나가 옮겨 가자 background, content, popup, side panel, manifest가 서로 다른 말을 하기 시작했어. Anchor 10은 그걸 고쳐. JavaScript owner는 하나로, JSON이 상속 못 하는 경계는 숨기지 않고 명시적으로."
새 owner를 가질 자격을 만든 bug
ChromeEmbed는 네 extension realm에서 같은 cwkPippa frontend를 봐. Service worker는 tab이 이미 Pippa surface인지 판별하고, content script는 self-capture를 막아. Popup은 Frontend selector를 만들고 side panel은 후보 origin을 순서대로 probe해. v0.2.1 전에는 realm마다 host literal을 따로 들고 있었어. Tailnet 주소가 한 번 바뀌자 일부만 교체됐고 extension이 자기 자신과 불일치했지. 이건 보기 싫은 중복이 아니라, consumer 넷이 쓰는 제품 fact 하나가 실제로 실패한 사건이야.
Classic-script loader 넷
- Service worker: router를 읽기 전에
importScripts('pippa-hosts.js'). - Content script: manifest의
content_scripts.js에서pippa-hosts.js를content-script.js보다 먼저. - Popup:
popup.html이 registry script를popup.js보다 먼저. - Side panel:
sidepanel.html이 registry를sidepanel.js보다 먼저.
네 surface가 extension 전체의 runtime global 하나를 공유하는 건 아니야. 각 realm이 같은 파일을 자기 classic-script global 환경에 올려. 그래서 선언도 일부러 const가 아니라 var를 써. Extension reload 뒤 이미 registry를 본 isolated world에 content script가 다시 들어갈 수 있거든. Top-level const 재선언은 터지지만 var 재선언은 아무 일도 안 일어나.
Manifest는 없앨 수 없는 중복
manifest.json은 script가 아니라 data고 MV3에는 import가 없어. 그래서 세 묶음은 review와 verifier로 함께 맞춰야 해. host_permissions, content_scripts.exclude_matches, 그리고 extension-page CSP 안의 connect-src와 frame-src야. 맡은 일도 다 달라. Permission은 network surface를 합법으로 만들고, exclusion은 ChromeEmbed가 자기 embed route를 다시 읽는 걸 막아. connect-src는 reachability probe를, frame-src는 iframe 시도를 허용해. 그래도 상대 response가 framing을 거절하면 iframe은 못 떠.
Serialize된 function에는 closure가 없어
Worker에는 extension reload보다 먼저 열린 tab을 위한 chrome.scripting.executeScript({ func }) fallback도 있어. Chrome은 그 function을 serialize해서 보내기 때문에 worker scope의 PIPPA_LOCAL_HOSTS를 closure로 잡지 못해. Allowlist를 args로 직접 실어 보내야 해. 평범한 nested function은 바깥 환경을 잡으니 더 헷갈리기 쉬워. Injected function은 closure가 아니라 code shipment야.
Public material에는 invariant가 하나 더 있어
실제 office 주소는 운영 설정이지 quest content가 아니야. 공개 예제는 100.x.x.x만 써. 좋은 consistency check는 두 가지를 동시에 증명해야 해. 공개 surface의 host가 전부 맞고, private literal은 하나도 새지 않았다는 것. Consolidation은 owner, 피할 수 없는 manifest 중복, loader 순서, redaction 경계가 다 보일 때 끝나.