@preventive/triage 1.0.0-alpha.50 → 1.0.0-alpha.51
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/common/managed/finding-detail.d.ts +2 -1
- package/common/managed/finding-detail.js +43 -9
- package/common/managed/npm-packages.d.ts +2 -0
- package/common/managed/npm-packages.js +18 -1
- package/common/managed/routes.js +19 -7
- package/common/managed/team-app.d.ts +1 -0
- package/common/managed/team-app.js +17 -1
- package/out/activity.js +4 -4
- package/out/{chunk-75YLHBCM.js → chunk-2K6UN3PC.js} +1 -1
- package/out/{chunk-2WDZPXVL.js → chunk-7JBSSRD7.js} +1 -1
- package/out/{chunk-4XMP7YVH.js → chunk-FMXWXDR4.js} +1 -1
- package/out/chunk-HT2SSA3V.js +1 -0
- package/out/chunk-IPAH4LKF.js +232 -0
- package/out/{chunk-FKBXNUW4.js → chunk-KOGNQDSJ.js} +1 -1
- package/out/{chunk-UK7RGJT6.js → chunk-VDRXHIHN.js} +2 -2
- package/out/{chunk-HTBYHSPG.js → chunk-WRAJVD35.js} +1 -1
- package/out/client-managed-import.js +1 -1
- package/out/client-managed.js +25 -25
- package/out/compare.js +14 -14
- package/out/dialogs.js +41 -41
- package/out/graph.js +1 -1
- package/out/index.html +6 -6
- package/out/scan.js +2 -2
- package/out/view.css +1 -1
- package/out/view.js +7 -7
- package/package.json +3 -1
- package/server-managed/agent-merges.ts +1 -1
- package/server-managed/app-agents.ts +4 -2
- package/server-managed/commit-lockfiles.ts +7 -4
- package/server-managed/comparison.ts +13 -2
- package/server-managed/db-neon.ts +13 -3
- package/server-managed/db.ts +2 -1
- package/server-managed/dependency-review-comments.ts +16 -18
- package/server-managed/dependency-reviews.ts +45 -27
- package/server-managed/github-app.ts +3 -42
- package/server-managed/github-requests.ts +97 -0
- package/server-managed/http.ts +249 -75
- package/server-managed/listed-activity.ts +39 -0
- package/server-managed/locked-packages.ts +28 -5
- package/server-managed/npm-kept.ts +14 -4
- package/server-managed/npm-patch.ts +325 -0
- package/server-managed/pull-dependencies.ts +9 -6
- package/server-managed/pull-dependency-reviews.ts +19 -13
- package/server-managed/repository-agents.ts +162 -69
- package/server-managed/repository-dependency-reviews.ts +6 -5
- package/server-managed/repository-pulls.ts +114 -58
- package/server-managed/repository-pulse.ts +1 -1
- package/server-managed/reviewed-dependencies.ts +4 -5
- package/server-managed/team-reports.ts +19 -7
- package/out/chunk-6S2U2UYG.js +0 -232
- package/out/chunk-FC65TPUB.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as e}from"./chunk-NRPC74AM.js";import{a as t,d as n,f as r,h as i}from"./chunk-7C7DWL7I.js";import{d as a}from"./chunk-PNHBZGDD.js";import{a as o,b as s}from"./chunk-
|
|
1
|
+
import{b as e}from"./chunk-NRPC74AM.js";import{a as t,d as n,f as r,h as i}from"./chunk-7C7DWL7I.js";import{d as a}from"./chunk-PNHBZGDD.js";import{a as o,b as s}from"./chunk-2K6UN3PC.js";import{c}from"./chunk-HT2SSA3V.js";import{C as l,D as u,G as d,J as f,K as p,L as m,O as h,q as g}from"./chunk-SXV2T5C4.js";import{a as _}from"./chunk-TUII34K2.js";function v(e,t){let n=s([{groups:[e],tree:t.tree,treeDependencies:t.treeDependencies}]);for(let r of e)l(r,t),r.isApp??=g(r,r.source??t.source),r._depsDirectory=n}function y(e,t){return!(e.isApp??g(e,e._source??e.source))&&o(e.file,e._depsDirectory??t??s([{groups:[[e]]}]))}function ee(e,n,r){let i=t(n);return i===`ignored`&&y(e,r)?void 0:i}function b(e,n,a,o){let s=n.id??String(n._id),c=n._reportName??``;y(n,o)&&(a===`ignored`||a===`untriaged`)?(t(e.get(s))!==`ignored`&&r(e,s,{triage:void 0}),i(e,s,c,a===`ignored`,!0)):(r(e,s,{triage:a===`untriaged`?void 0:a}),a!==`ignored`&&a!==`untriaged`&&i(e,s,c,!1))}function x(e,a){let o=new Set;for(let t of e.values()){let e=t?.ignoredReports;if(!e?.length)continue;let r=new Set(e).size!==e.length;for(let i of e)(r||!n(t,i))&&o.add(i)}if(o.size===0)return!1;let c=!1;for(let l of a){let a=(l.groups??[]).flat();if(!a.some(e=>o.has(e._reportName??l.name??l.fileName??``)))continue;let u=s([l]),d=e=>({...e,_source:e._source??e.source??l.source}),f=new Set(a.filter(e=>y(d(e),u)).map(e=>e.id??String(e._id)));for(let o of a){let a=o.id??String(o._id),s=o._reportName??l.name??l.fileName??``,p=e.get(a);p?.ignoredReports?.includes(s)&&(n(p,s)||y(d(o),u)||(t(p)||(c=r(e,a,{triage:`ignored`})||c),f.has(a)||(c=i(e,a,s,!1)||c)))}for(let t of a){if(!y(d(t),u))continue;let n=t.id??String(t._id),r=t._reportName??l.name??l.fileName??``;e.get(n)?.ignoredReports?.includes(r)&&(c=i(e,n,r,!0,!0)||c)}}return c}async function S(e,t){let r=new Set(Object.values(e??{}).flatMap(e=>Array.isArray(e?.ignoredReports)?e.ignoredReports.filter(t=>typeof t==`string`&&!n(e,t)):[])),i=[];for(let e of r){let n;try{let r=await t(e);if(typeof r!=`string`)continue;n=await h(r)}catch{continue}n&&i.push({...n.data,name:e,groups:[n.findings]})}return i}async function C(e,t){if(e!=null&&(typeof e!=`object`||Array.isArray(e)))return{entries:e,changed:!1};let n=new Map(Object.entries(e??{})),r=x(n,await S(e,t));return{entries:Object.fromEntries(n),changed:r}}var w=`links`;function T(e){if(typeof e==`string`)return e.length>0?e:null;if(!e||typeof e!=`object`||Array.isArray(e))return null;let{id:t}=e;return typeof t==`string`&&t.length>0?t:null}function E(e){if(typeof e==`string`&&!/^\s*\[/u.test(e))return null;let t;try{t=JSON.parse(e)}catch{return null}if(!Array.isArray(t)||t.length===0)return null;let n=[],r=0;for(let e of t){if(!Array.isArray(e))return null;let t=new Set;for(let n of e){let e=T(n);if(e===null)return null;c(e)?t.add(e):r++}t.size>1&&n.push([...t])}return{groups:n,skipped:r}}function D(e){let t=new Set;for(let n of e)for(let e of n)t.add(e);return t.size}function te(e,t){for(let n of e)for(let e of n){let r=t.get(e);r||t.set(e,r=new Set);for(let t of n)t!==e&&r.add(t)}return t}var O=1,k=16,A=12,j=1+k+A+16,M=1+k+A;async function N(e,t){let n=await crypto.subtle.importKey(`raw`,_(e),`PBKDF2`,!1,[`deriveKey`]);return crypto.subtle.deriveKey({name:`PBKDF2`,hash:`SHA-256`,salt:t,iterations:3e6},n,{name:`AES-GCM`,length:256},!1,[`encrypt`,`decrypt`])}function P(e){return!(e instanceof Uint8Array)||e.length<j?!1:e[0]===O}async function F(e,t){if(!(e instanceof Uint8Array))throw TypeError(`encryptWithPassword: plaintext Uint8Array required`);if(typeof t!=`string`||!t)throw TypeError(`encryptWithPassword: password required`);let n=new Uint8Array(M+e.length+16);n[0]=O,crypto.getRandomValues(n.subarray(1,1+k)),crypto.getRandomValues(n.subarray(1+k,M));let r=n.subarray(1,1+k),i=n.subarray(1+k,M),a=await N(t,r),o=new Uint8Array(await crypto.subtle.encrypt({name:`AES-GCM`,iv:i,additionalData:n.subarray(0,M)},a,e));return n.set(o,M),n}async function ne(e,t){if(typeof t!=`string`||!t)throw TypeError(`tryDecryptWithPassword: password required`);if(!(e instanceof Uint8Array)||e.length<j||e[0]!==O)return{ok:!1,reason:`malformed`};let n=e.subarray(1,1+k),r=e.subarray(1+k,M),i=e.subarray(M),a=await N(t,n),o;try{o=new Uint8Array(await crypto.subtle.decrypt({name:`AES-GCM`,iv:r,additionalData:e.subarray(0,M)},a,i))}catch{return{ok:!1,reason:`wrong-password`}}return{ok:!0,plaintext:o}}async function I(e,t,n){if(!n||typeof n.malformedMsg!=`string`||typeof n.wrongPasswordMsg!=`string`)throw TypeError(`decryptWithPasswordOrThrow: { malformedMsg, wrongPasswordMsg } strings required`);let r=await ne(e,t);if(r.ok)return r.plaintext;throw r.reason===`wrong-password`?Error(n.wrongPasswordMsg):Error(n.malformedMsg)}var L=P,R=F;function z(e,t){return I(e,t,{malformedMsg:`malformed encrypted bundle`,wrongPasswordMsg:`wrong password or corrupt bundle`})}var B=1,V=1024,H=1024,U=200,W=104857600,G=Math.ceil(W*4/3)+16,K=512,q=64;function J(e){if(!e||typeof e!=`object`)return`payload is not an object`;if(e.version!==B)return`unsupported export version: ${e.version}`;if(!e.workspace||typeof e.workspace!=`object`)return`workspace metadata missing`;if(typeof e.workspace.id!=`string`)return`workspace.id must be a string`;if(typeof e.workspace.name!=`string`)return`workspace.name must be a string`;if(typeof e.workspace.privateKey!=`string`)return`workspace.privateKey must be a string`;if(e.workspace.createdAt!==void 0&&!Number.isFinite(e.workspace.createdAt))return`workspace.createdAt must be a finite number or omitted`;if(!Array.isArray(e.reports))return`reports field must be an array`;if(e.reports.length>H)return`reports count (${e.reports.length}) exceeds cap (${H})`;if(e.bundles!==void 0){if(!Array.isArray(e.bundles))return`bundles field must be an array when present`;if(e.bundles.length>V)return`bundles count (${e.bundles.length}) exceeds cap (${V})`;for(let t of e.bundles){if(typeof t!=`string`)return`bundles entries must be strings`;if(t.length>U)return`bundle integrity exceeds per-entry length cap (${U})`}}if(e.bundleBlobs!==void 0){if(!Array.isArray(e.bundleBlobs))return`bundleBlobs field must be an array when present`;if(e.bundleBlobs.length>q)return`bundleBlobs count (${e.bundleBlobs.length}) exceeds cap (${q})`;for(let t of e.bundleBlobs){if(!t||typeof t!=`object`||Array.isArray(t))return`bundleBlobs entries must be objects`;if(typeof t.integrity!=`string`||t.integrity.length===0)return`bundleBlobs.integrity must be a non-empty string`;if(t.integrity.length>U)return`bundleBlobs.integrity exceeds per-entry length cap (${U})`;if(typeof t.name!=`string`||t.name.length===0)return`bundleBlobs.name must be a non-empty string`;if(t.name.length>K)return`bundleBlobs.name exceeds per-entry length cap (${K})`;if(t.name.includes(`\0`))return`bundleBlobs.name cannot contain NUL`;if(typeof t.data!=`string`)return`bundleBlobs.data must be a base64 string`;if(t.data.length>G)return`bundleBlobs.data exceeds per-blob size cap (${W} bytes raw)`}}return null}async function Y(e){return new Uint8Array(await e.arrayBuffer())}async function X(e,t){if(L(e)){if(typeof t!=`string`||!t)throw TypeError(`parseWorkspaceBundleBytes: password required for encrypted bundle`);let n=await z(e,t);try{return Z(await a(n))}catch(e){throw Error(`wrong password or corrupt bundle`,{cause:e})}}let n;try{n=await a(e)}catch(e){throw Error(`gzip decompression failed: ${e.message}`,{cause:e})}return Z(n)}function Z(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`payload is not JSON: ${e.message}`,{cause:e})}let n=J(t);if(n===null)return t;let r=n.includes(`exceeds cap`);throw Error(r?n:`not a deepview workspace export: ${n}`)}function Q(e,t){let n=e.trimStart().startsWith(`[`)?E(e):null;if(n)return{data:{source:`links`,findings:[],links:n.groups},format:`links`,reason:null};let r=m(e);if(r.data!=null||p(e,t)!==`codex`)return r;try{return{data:{type:`security`,source:`codex-security`,findings:d(e).flatMap(e=>e.data.findings)},format:`codex`,reason:null}}catch(e){return{data:null,format:null,reason:e instanceof Error?e.message:`Invalid Codex CSV`}}}function re(e,t){let n=Q(e,t);return n.data==null?Promise.resolve(null):h(JSON.stringify(n.data))}function ie(e){let t=new Set;for(let n of e){if(!n||typeof n!=`object`)continue;let e=n;typeof e.file==`string`&&e.file&&t.add(e.file);for(let n of Array.isArray(e.evidence)?e.evidence:[])typeof n?.file==`string`&&n.file&&t.add(n.file)}return t}function $(e){let t=(f(e)??[]).flat().filter(e=>typeof e==`object`&&!!e),n=s([{groups:[t],tree:e?.tree}]);return{directory:n,own:t.filter(e=>!o(e.file,n))}}function ae(e){let t=new Map;for(let n of $(e).own){let e=u(n);e&&t.set(e.toLowerCase(),e)}return t.size===1?[...t.values()][0]:null}function oe(t){let{directory:n,own:r}=$(t);return e([...ie(r)].filter(e=>!o(e,n)))}var se=[`inprogress`,`fixed`,`invalid`,`deleted`,`ignored`];function ce(e){return typeof e==`string`&&se.includes(e)}function le(e){if(e===null)return null;if(typeof e!=`object`||Array.isArray(e))return`invalid`;let t=e,n={},r=t.color;if(r!=null){if(typeof r!=`string`||r.length>50)return`invalid`;r!==``&&(n.color=r)}let i=t.triage;if(i!=null){if(!ce(i))return`invalid`;n.triage=i}for(let e of[`comment`,`fix`]){let r=t[e];if(r!=null){if(typeof r!=`string`||r.length>1e4)return`invalid`;r!==``&&(n[e]=r)}}let a=t.flagged;if(a!=null){if(typeof a!=`boolean`)return`invalid`;n.flagged=a}return n}export{v as a,y as b,ee as c,b as d,x as e,S as f,C as g,w as h,E as i,D as j,te as k,F as l,I as m,L as n,R as o,H as p,Y as q,X as r,Z as s,Q as t,re as u,ae as v,oe as w,le as x};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as e}from"./chunk-QB4CBOX2.js";import{b as t,c as n,e as r,f as i,g as a}from"./chunk-6LNQTKAV.js";import{
|
|
1
|
+
import{a as e}from"./chunk-QB4CBOX2.js";import{b as t,c as n,e as r,f as i,g as a}from"./chunk-6LNQTKAV.js";import{k as o}from"./chunk-HT2SSA3V.js";import{J as s}from"./chunk-SXV2T5C4.js";import{a as c}from"./chunk-TUII34K2.js";var l=[`dependencies`,`security`],u={dependencies:`Dependencies`,security:`Security`},d=e(),f=Object.freeze(d.models),p=d.defaultModel,m=`x-upload-encryption`,h=1,g=1,_={name:`X25519`},v=34,y=1048576,b=65536,x=`deepview-managed-upload.v1.content-key`;function S(e,t){let n=new Uint8Array(12);return new DataView(n.buffer).setUint32(7,e),n[11]=+!!t,n}async function C(e,t,n){let r=await crypto.subtle.importKey(`raw`,e,`HKDF`,!1,[`deriveKey`]);return await crypto.subtle.deriveKey({name:`HKDF`,hash:`SHA-256`,salt:t,info:c(x)},r,{name:`AES-GCM`,length:256},!1,[n])}async function w(e){let t=new Uint8Array(await e.slice(0,b).arrayBuffer());if(t.includes(0))return!1;try{return new TextDecoder(`utf-8`,{fatal:!0}).decode(t,{stream:!0}),!0}catch{return!1}}async function T(e,t,n){let r=await w(e),[i,a]=await Promise.all([crypto.subtle.importKey(`raw`,t,_,!1,[]),crypto.subtle.generateKey(_,!1,[`deriveBits`])]),o=new Uint8Array(v);o[0]=h,o[1]=r?g:0,o.set(new Uint8Array(await crypto.subtle.exportKey(`raw`,a.publicKey)),2);let s=await C(await crypto.subtle.deriveBits({name:`X25519`,public:i},a.privateKey,256),o,`encrypt`),c=[new Blob([o])],l=new Uint8Array(y),u=0,d=0,f=async e=>{c.push(new Blob([await crypto.subtle.encrypt({name:`AES-GCM`,iv:S(d++,e)},s,l.subarray(0,u))])),u=0},p=(r?e.stream().pipeThrough(new CompressionStream(`gzip`)):e.stream()).getReader();try{for(let e=await p.read();!e.done;e=await p.read()){n?.throwIfAborted();for(let t=0;t<e.value.length;){u===y&&await f(!1);let n=Math.min(y-u,e.value.length-t);l.set(e.value.subarray(t,t+n),u),u+=n,t+=n}}}catch(e){throw await p.cancel(e).catch(()=>{}),e}return await f(!0),new Blob(c)}var E=null,D=0;function O(){return E?.user.role??null}function k(e){if(e!==null&&!i(e))throw TypeError(`Unknown managed preview role: ${e}. Expected ${r.join(`, `)}.`);D++,E=e===null?null:{user:{id:`preview:${e}`,login:e,name:e[0].toUpperCase()+e.slice(1),role:e,avatarUrl:null,lastSeenAt:Date.now(),lastActivityAt:null},csrfToken:null}}function ee(e,t){let n=new URL(e,`http://managed-preview.invalid`).pathname,r=(t?.method??`GET`).toUpperCase();if(r===`POST`&&n===`/api/auth/logout`)return Response.json({ok:!0});if(r!==`GET`)throw Error(`Changes are not saved in the managed UI preview`);if(n===`/api/auth/session`)return Response.json(E);if(n===`/api/teams`)return Response.json({teams:[]});if(n.startsWith(`/api/admin/`)&&!a(E.user.role,`manage`)||[`/api/admin/users`,`/api/admin/teams`,`/api/admin/repositories`,`/api/admin/repositories/aliases`,`/api/admin/repositories/risk`].includes(n)&&E.user.role!==`admin`)return Response.json({error:`forbidden`},{status:403});if(n===`/api/admin/repositories/risk`)return new Response(`{"type":"repos","repos":[]}
|
|
2
2
|
{"type":"done"}
|
|
3
|
-
`,{headers:{"content-type":`application/x-ndjson`}});let i={"/api/admin/users":{users:[E.user]},"/api/admin/teams":{teams:[],users:[E.user],repos:[],permissions:l},"/api/admin/links":{shares:[]},"/api/admin/repositories":{repositories:[],total:0,connectedCount:0,installUrl:null,tokenMissing:!1},"/api/admin/repositories/aliases":{aliases:[],repos:[]},"/api/admin/repositories/resolve":{location:null},"/api/admin/reports":{reports:[],repos:[],maxBytes:26214400},"/api/admin/bundles":{bundles:[],repos:[],maxBytes:209715200},"/api/admin/history":{history:[],total:0,page:1,limit:100,filters:{repos:[],users:[]}},"/api/admin/scan/models":{models:f,defaultModel:p},"/api/admin/scan-results":{bundles:[],results:[]},"/api/auth/profile":{profile:{login:E.user.login,name:E.user.name,githubName:E.user.name,nameAccount:null,avatarAccount:null,accounts:[]}}};return Object.hasOwn(i,n)?Response.json(i[n]):Response.json({error:`not-found`},{status:404})}var A=3145728,j=new Set([`/api/admin/reports`,`/api/admin/bundles`,`/api/admin/deduplication`]);async function M(e,t){let n=await t(`/api/admin/uploads/key`,{credentials:`same-origin`,signal:e.signal});if(n.status===404||n.status===405)return e;if(!n.ok)return n;let r=(await n.json())?.key;if(typeof r!=`string`)throw Error(`The server sent an invalid upload key`);let i=new Headers(e.headers);return i.set(m,`1`),{...e,headers:i,body:await T(e.body,Uint8Array.fromBase64(r,{alphabet:`base64url`}),e.signal)}}async function N(e,t,n){let r=null;if(e!==`/api/admin/deduplication`&&t.body.size>A){let i=await n(`/api/config`,{credentials:`same-origin`,signal:t.signal});if(!i.ok)return i;let a=(await i.json()).managed,o=a?.uploadMaxBytes?.[e.endsWith(`/reports`)?`reports`:`bundles`];if(Number.isSafeInteger(o)&&o>0&&t.body.size>o)return Response.json({error:`too-large`},{status:413});let s=a?.uploadChunkBytes;Number.isSafeInteger(s)&&s>0&&s<=A&&(r=s)}let i=await M(t,n);return i instanceof Response?i:r==null||i.body.size<=A?await n(e,i):await F(e,i,n,r)}var P=3;async function F(e,t,n,r){let i=t.body,a=crypto.randomUUID(),o=e.endsWith(`/reports`)?`reports`:`bundles`,s=Math.ceil(i.size/r),c=new Headers(t.headers);c.set(`content-type`,`application/octet-stream`);let l=0,u=!1;try{let d=null,f=!1,p=(await Promise.allSettled(Array.from({length:Math.min(P,s)},async()=>{for(;!f&&l<s;){let e=l++;try{let s=await n(`/api/admin/uploads/${o}/${a}/${e}`,{...t,headers:c,body:i.slice(e*r,(e+1)*r)});s.ok||(d??=s,f=!0)}catch(e){throw f=!0,e}}}))).find(e=>e.status===`rejected`);if(p)throw p.reason;if(d)return d;let m=new Headers(t.headers);m.set(`x-upload-id`,a),m.set(`x-upload-parts`,String(s)),m.set(`x-upload-size`,String(i.size));let h=await n(e,{...t,headers:m,body:``});return u=h.ok,h}finally{if(!u&&l>0){let e=new Headers(t.headers);e.set(`x-upload-parts`,String(l)),await n(`/api/admin/uploads/${o}/${a}`,{...t,method:`DELETE`,headers:e,body:void 0,signal:AbortSignal.timeout(1e4)}).catch(()=>{})}}}async function I(e){await e.json().then(e=>e?.error,()=>null)===`view-only`&&globalThis.document?.dispatchEvent(new CustomEvent(`managed-view-only`))}async function L(e,n){if(n?.signal?.throwIfAborted(),E)return ee(e,n);let r=D;async function i(e,n){if(r!==D)throw new DOMException(`Managed session changed`,`AbortError`);let i=t();if(i){if(new URL(e,globalThis.location.origin).origin!==globalThis.location.origin)throw Error(`Public workspace requests must be same-origin`);let t=new Headers(n?.headers);t.set(`x-deepview-share`,i.token),n={...n,headers:t,credentials:`omit`,redirect:`error`}}let a=await fetch(e,{...n,cache:`no-store`});if(r!==D)throw new DOMException(`Managed session changed`,`AbortError`);return a.status===403&&![`GET`,`HEAD`].includes((n?.method??`GET`).toUpperCase())&&I(a.clone()),a}return n?.method===`POST`&&j.has(e)&&n.body instanceof Blob?await N(e,n,i):await i(e,n)}var R=new class{constructor(e=()=>{}){this.resources=new Map,this.session=null,this.teamCatalog=null,this.reportCatalog=null,this.bundleCatalog=null,this.generation=0,this.sessionController=new AbortController,this.notify=e}setSession(e){(this.session?.id!==e?.id||this.session?.role!==e?.role)&&this.reset(),this.session=e}reset(){this.generation++,this.sessionController.abort(),this.sessionController=new AbortController,this.invalidate(),this.session=null,this.teamCatalog=null,this.reportCatalog=null,this.bundleCatalog=null}setReportCatalog(e){let t=new Set,n=new Map(e.map(e=>[e.id,JSON.stringify([e.cacheKey??null,e.reports.map(e=>[e.id,e.cacheKey??null,e.visible!==!1]).toSorted(),(e.bundles??[]).map(e=>[e.id,e.filename,e.repoFullName,e.repoDirectory??``]).toSorted()])]));for(let e of new Set([...this.teamCatalog?.keys()??[],...n.keys()]))this.teamCatalog?.get(e)!==n.get(e)&&t.add(`team:${e}`);for(let e of this.resources.keys())if(e.startsWith(`reports:content:team:`)){let[t]=e.slice(21).split(`:`);(!n.has(t)||this.teamCatalog?.get(t)!==n.get(t))&&this.invalidate([e])}this.teamCatalog=n;let r=new Map;for(let t of e)for(let e of t.reports){let n=r.get(e.id)??[];n.push(JSON.stringify([t.id,e.cacheKey??null])),r.set(e.id,n)}let i=new Map([...r].map(([e,t])=>[e,JSON.stringify(t.toSorted())])),a=this.reportCatalog;this.reportCatalog=i;let o=new Set(t);for(let e of new Set([...a?.keys()??[],...i.keys()]))a?.get(e)!==i.get(e)&&o.add(e);for(let e of this.resources.keys()){if(!e.startsWith(`reports:content:`)||e.startsWith(`reports:content:team:`))continue;let t=e.slice(16);(!i.has(t)||o.has(t))&&(this.invalidate([e]),o.add(t))}let s=new Map;for(let t of e)for(let e of t.bundles??[]){let n=s.get(e.id)??[];n.push(JSON.stringify([t.id,t.cacheKey??null,e.filename,e.repoFullName,e.repoDirectory??``])),s.set(e.id,n)}let c=!1,l=new Map([...s].map(([e,t])=>[e,JSON.stringify(t.toSorted())]));for(let e of new Set([...this.bundleCatalog?.keys()??[],...l.keys()]))this.bundleCatalog?.get(e)!==l.get(e)&&(c=!0,o.add(`bundle:${e}`),this.invalidate([`bundle-metadata:${e}`]));this.bundleCatalog=l;for(let e of this.resources.keys()){if(!e.startsWith(`report-sources:`)&&!e.startsWith(`finding-history:`))continue;let[,n,r]=e.split(`:`);(n?t.has(`team:${n}`):c||o.has(r))&&this.invalidate([e])}return o}read(e){return this.resources.get(e)?.data}invalidate(e){for(let[t,n]of this.resources)e&&!e.some(e=>t===e||t.startsWith(`${e}:`))||(n.controller?.abort(),this.resources.delete(t))}async mutate(e,t){let n=this.generation,r;try{r=await e()}catch(e){throw n===this.generation&&e?.name!==`AbortError`&&this.notify(`Couldn't save changes: ${e?.message??e}`),e}if(n!==this.generation)throw new DOMException(`Managed session changed`,`AbortError`);return this.invalidate(t),r}async load(e,t,n,{signal:r,apply:i=()=>{},retryInvalidated:a=!1}={}){let o=this.generation;for(;;){r?.throwIfAborted();let s=this.resources.get(e);if(s||(s={},this.resources.set(e,s)),s.data!==void 0&&i(s.data),!s.pending){let e=s.controller=new AbortController;s.pending=(async()=>{try{let t=await n(e.signal);return e.signal.throwIfAborted(),s.data=t,t}catch(n){throw!e.signal.aborted&&n?.name!==`AbortError`&&this.notify(`Couldn't refresh ${t}: ${n?.message??n}`),n}})().finally(()=>{s.pending=null})}try{let t=await s.pending;if(r?.throwIfAborted(),this.resources.get(e)!==s)throw new DOMException(`Managed data changed`,`AbortError`);return i(t),t}catch(t){if(!a||t?.name!==`AbortError`||r?.aborted||o!==this.generation||this.resources.get(e)===s)throw t}}}}(e=>{document.dispatchEvent(new CustomEvent(`managed-notice`,{detail:{message:e}}))});function z(e){R.setSession(e)}function B(e){return R.setReportCatalog(e)}function V(){R.reset()}async function H(e,t=null,n={}){let r;try{r=await L(e,{credentials:`same-origin`,headers:{accept:`application/json`},...n})}catch{return t}if(r.status===401||r.status===403)return null;if(!r.ok)return t;try{return await r.json()}catch{return t}}async function U({fallback:e=null,sent:r}={}){let i=t()||O()!==null?void 0:await r;if(i===null)return null;let a=W(i);if(a!==void 0)return a;let o;try{let r=t(),i=await L(r?n(r):`/api/auth/session`,{credentials:`same-origin`,headers:{accept:`application/json`}});if(i.status===401||i.status===403)return null;if(!i.ok)return e;o=await i.json()}catch{return e}let s=W(o);return s===void 0?e:s}function W(e){let n=e?.user;if(n===null)return null;if(n!==void 0&&typeof n.login==`string`)return{id:n.id,login:n.login,name:typeof n.name==`string`?n.name:null,avatarUrl:typeof n.avatarUrl==`string`?n.avatarUrl:null,role:typeof n.role==`string`?n.role:`none`,csrfToken:typeof e.csrfToken==`string`?e.csrfToken:null,...t()?{publicShare:!0}:{},...typeof e.viewer?.login==`string`?{viewer:{id:e.viewer.id,login:e.viewer.login,name:typeof e.viewer.name==`string`?e.viewer.name:null}}:{},...!t()&&e.dependencyReview===!0?{dependencyReview:!0}:{}}}function G(e){let t=t=>Number.isSafeInteger(e?.[t])&&e[t]>=0;return e?.appMode===!1?{appMode:!1,...t(`appReports`)&&{appReports:e.appReports},...t(`findings`)&&{findings:e.findings}}:e?.appMode===!0&&t(`appFindings`)?{appMode:!0,appFindings:e.appFindings}:null}function te(e){if(typeof e?.sha!=`string`||typeof e.github!=`string`||!Array.isArray(e.tags))return null;let t=e.details,n=e=>typeof e==`string`?e:null,r=e=>Number.isSafeInteger(e)?e:null;return{sha:e.sha,github:e.github,tags:e.tags.filter(e=>typeof e==`string`),details:typeof t?.subject==`string`?{subject:t.subject,authorName:n(t.authorName),authorLogin:n(t.authorLogin),authoredAt:r(t.authoredAt),committedAt:r(t.committedAt)}:null}}async function K({fallback:e=[],signal:r,onRevision:i}={}){let a=t(),o=a?await H(n(a),null,{signal:r}):null,s=a?{teams:o?.team?[o.team]:[]}:await H(`/api/teams`,{teams:e},{signal:r}),c=s?.teams;return Array.isArray(c)?(i?.(typeof s.revision==`string`?s.revision:null),c.filter(e=>e!=null&&typeof e.id==`string`&&typeof e.name==`string`).map(e=>({id:e.id,slug:e.slug,name:e.name,...!a&&e.dependencyReview===!0?{dependencyReview:!0}:{},...e.permissions?{permissions:{dependencies:e.permissions.dependencies===!0,security:e.permissions.security===!0}}:{},...typeof e.cacheKey==`string`?{cacheKey:e.cacheKey}:{},...G(e.app)?{app:G(e.app)}:{},repos:Array.isArray(e.repos)?e.repos.filter(e=>Number.isSafeInteger(e?.repoId)&&e.repoId>0&&typeof e.fullName==`string`).map(e=>({repoId:e.repoId,fullName:e.fullName,path:typeof e.path==`string`&&e.path?e.path:null})):[],reports:Array.isArray(e.reports)?e.reports.filter(e=>e!=null&&typeof e.id==`string`&&typeof e.filename==`string`).map(e=>({id:e.id,slug:e.slug,filename:e.filename,visible:e.visible!==!1,...e.analyzer===null||typeof e.analyzer==`string`?{analyzer:e.analyzer}:{},repoFullName:typeof e.repoFullName==`string`?e.repoFullName:``,repoDirectory:typeof e.repoDirectory==`string`?e.repoDirectory:``,...typeof e.cacheKey==`string`?{cacheKey:e.cacheKey}:{}})):[],bundles:Array.isArray(e.bundles)?e.bundles.filter(e=>e!=null&&typeof e.id==`string`&&typeof e.filename==`string`).map(e=>({id:e.id,slug:e.slug,integrity:e.integrity,byteSize:e.byteSize,repoId:e.repoId,filename:e.filename,kind:e.kind,visible:e.visible!==!1,summary:e.summary??null,summaryRetryAt:Number.isSafeInteger(e.summaryRetryAt)&&e.summaryRetryAt>0?e.summaryRetryAt:null,repoDirectory:typeof e.repoDirectory==`string`?e.repoDirectory:``,repoFullName:typeof e.repoFullName==`string`?e.repoFullName:``,commitInfo:te(e.commitInfo)})):[]}))):s==null?[]:e}function q(e){return e?.links===void 0?[]:Array.isArray(e.links)&&e.links.every(e=>Array.isArray(e)&&e.length>=2&&e.every(e=>typeof e==`string`))?e.links:null}function J(e){return s(e?.data)===null||typeof e.repo?.directory!=`string`||e.repo.github!==null&&typeof e.repo.github!=`string`||q(e)===null?null:{data:e.data,repo:e.repo,...e.links?{links:e.links}:{}}}async function Y(e,{signal:t}={}){return J(await H(`/api/reports/${encodeURIComponent(e)}`,null,{signal:t}))}async function X(e,{signal:t}={}){let n=[...new Set(e)];if(n.length===0)return[];let r=await H(`/api/reports/query`,null,{method:`POST`,signal:t,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({ids:n})});if(!Array.isArray(r?.reports)||r.reports.length!==n.length)return null;let i=new Map;for(let e of r.reports){let t=J(e);if(!t||!n.includes(e.id)||i.has(e.id))return null;i.set(e.id,t)}let a=q(r);return a===null?null:e.map(e=>({...i.get(e),...a.length>0?{links:a}:{}}))}async function Z(e,{signal:t,reportId:n=null,lite:r=!1}={}){let i=new URLSearchParams(n===null?{}:{reportId:n});r&&i.set(`lite`,`1`);let a=await H(`/api/teams/${encodeURIComponent(e)}/reports${i.size>0?`?${i}`:``}`,null,{signal:t});if(!Array.isArray(a?.reports))return null;let o=[],s=new Set;for(let e of a.reports){let t=J(e);if(!t||typeof e.id!=`string`||typeof e.filename!=`string`||s.has(e.id))return null;s.add(e.id),o.push({id:e.id,filename:e.filename,...t})}let c=q(a);return c===null?null:(Object.defineProperty(o,"links",{value:c}),o)}function Q(e){return e?`?team=${encodeURIComponent(e)}`:``}async function ne(e,{reportId:t,...n}={}){let r=t==null?``:`?reportId=${encodeURIComponent(t)}`,i=await H(`/api/teams/${encodeURIComponent(e)}/annotations${r}`,null,n),{reports:a,entries:o,comments:s,issues:c={}}=i??{};if(!a||typeof a!=`object`||Array.isArray(a)||!o||typeof o!=`object`||Array.isArray(o)||!Array.isArray(s)||!c||typeof c!=`object`||Array.isArray(c)||Object.values(a).some(e=>!Array.isArray(e)||e.some(e=>typeof e!=`string`))||s.some(e=>!e||typeof e.findingId!=`string`))return null;let l=new Map;for(let[e,t]of s.entries()){let n=t.findingId,r=l.get(n)??[];r.push(e),l.set(n,r)}let u=new Map,d=new Map,f=typeof i.revision==`string`?i.revision:null;return Object.assign(e=>{if(!Object.hasOwn(a,e))return null;if(d.has(e))return d.get(e);let t=JSON.stringify(a[e]),n=u.get(t);if(!n){let r=[...new Set(a[e])],i=r.flatMap(e=>l.get(e)??[]);n={entries:Object.fromEntries(r.filter(e=>Object.hasOwn(o,e)).map(e=>[e,o[e]])),comments:i.toSorted((e,t)=>e-t).map(e=>s[e]),issues:Object.fromEntries(r.filter(e=>Object.hasOwn(c,e)).map(e=>[e,c[e]]))},u.set(t,n)}return d.set(e,n),n},{revision:f})}async function re(e,t,n){let r=(await H(`/api/reports/${encodeURIComponent(e)}/triage${Q(t)}`,null,n))?.entries;return typeof r==`object`&&r&&!Array.isArray(r)?r:null}async function ie(e,n,r=null){if(t())return[];let i=r===null?``:`?reportId=${encodeURIComponent(r)}`,a=await H(`/api/teams/${encodeURIComponent(e)}/fixes${i}`,null,{signal:n});return Array.isArray(a?.fixes)?a.fixes:null}async function ae(e,t,n){let r=await H(`/api/reports/${encodeURIComponent(e)}/comments${Q(t)}`,null,n);return Array.isArray(r?.comments)?r.comments:null}async function oe(e,{findingId:t,body:n,commentId:r=null,version:i},a,o){let s=r==null?``:`/${encodeURIComponent(r)}`;try{let c=await L(`/api/reports/${encodeURIComponent(e)}/comments${s}${Q(o)}`,{method:r==null?`POST`:`PATCH`,credentials:`same-origin`,headers:{"content-type":`application/json`,...a?{"x-csrf-token":a}:{}},body:JSON.stringify(r==null?{findingId:t,body:n}:{body:n,version:i})});return{status:c.status,comment:c.ok?(await c.json()).comment:null}}catch{return{status:0,comment:null}}}async function $(e,t,n,r,i){try{return(await L(`/api/reports/${encodeURIComponent(e)}/comments/${encodeURIComponent(t)}${Q(i)}`,{method:`DELETE`,credentials:`same-origin`,headers:{"content-type":`application/json`,...r?{"x-csrf-token":r}:{}},body:JSON.stringify({version:n})})).status}catch{return 0}}async function se(e,t,n,r){try{return(await L(`/api/reports/${encodeURIComponent(e)}/triage${Q(r)}`,{method:`POST`,credentials:`same-origin`,headers:{"content-type":`application/json`,...n?{"x-csrf-token":n}:{}},body:JSON.stringify({entries:t})})).status}catch{return 0}}function ce(e){e&&(location.href=e)}async function le(e){if(t()){location.href=`/`;return}try{await L(`/api/auth/logout`,{method:`POST`,credentials:`same-origin`,headers:e?{"x-csrf-token":e}:{}})}catch{}location.reload()}async function ue(e,t){let n=await L(`/api/auth/view-as`,{method:`POST`,credentials:`same-origin`,headers:{"content-type":`application/json`,...t?{"x-csrf-token":t}:{}},body:JSON.stringify({userId:e})});if(!n.ok)throw Error(`HTTP ${n.status}`);location.assign(`/`)}async function de(e){try{await L(`/api/auth/view-as`,{method:`DELETE`,credentials:`same-origin`,headers:e?{"x-csrf-token":e}:{}})}catch{}location.assign(o[`admin-users`])}async function fe(e){let t=await L(`/api/teams/${encodeURIComponent(e)}/share`,{credentials:`same-origin`});if(!t.ok)throw Error(`Could not load public links (${t.status})`);return(await t.json()).shares}async function pe(e,t,{id:n,revoke:r=!1,dependencies:i=!1,security:a=!1}={}){let o=n?`/${encodeURIComponent(n)}`:``,s=await L(`/api/teams/${encodeURIComponent(e)}/share${o}`,{method:r?`DELETE`:n?`PATCH`:`POST`,credentials:`same-origin`,headers:{"x-csrf-token":t,"content-type":`application/json`},...r?{}:{body:JSON.stringify({dependencies:i,security:a})}});if(!s.ok)throw Error(`Could not ${r?`revoke`:n?`update`:`create`} public link (${s.status})`);return s.json()}async function me(e,t){let n=await L(`/api/bundles/${encodeURIComponent(e)}/download`,{credentials:`same-origin`});if(!n.ok)throw Error(`Could not download bundle (${n.status})`);let r=URL.createObjectURL(await n.blob()),i=document.createElement(`a`);i.href=r,i.download=t,i.click(),setTimeout(()=>URL.revokeObjectURL(r),6e4)}export{u as a,O as b,k as c,L as d,R as e,z as f,B as g,V as h,U as i,K as j,Y as k,X as l,Z as m,Q as n,ne as o,re as p,ie as q,ae as r,oe as s,$ as t,se as u,ce as v,le as w,ue as x,de as y,fe as z,pe as A,me as B};
|
|
3
|
+
`,{headers:{"content-type":`application/x-ndjson`}});let i={"/api/admin/users":{users:[E.user]},"/api/admin/teams":{teams:[],users:[E.user],repos:[],permissions:l},"/api/admin/links":{shares:[]},"/api/admin/repositories":{repositories:[],total:0,connectedCount:0,installUrl:null,tokenMissing:!1},"/api/admin/repositories/aliases":{aliases:[],repos:[]},"/api/admin/repositories/resolve":{location:null},"/api/admin/reports":{reports:[],repos:[],maxBytes:26214400},"/api/admin/bundles":{bundles:[],repos:[],maxBytes:209715200},"/api/admin/history":{history:[],total:0,page:1,limit:100,filters:{repos:[],users:[]}},"/api/admin/scan/models":{models:f,defaultModel:p},"/api/admin/scan-results":{bundles:[],results:[]},"/api/auth/profile":{profile:{login:E.user.login,name:E.user.name,githubName:E.user.name,nameAccount:null,avatarAccount:null,accounts:[]}}};return Object.hasOwn(i,n)?Response.json(i[n]):Response.json({error:`not-found`},{status:404})}var A=3145728,j=new Set([`/api/admin/reports`,`/api/admin/bundles`,`/api/admin/deduplication`]);async function M(e,t){let n=await t(`/api/admin/uploads/key`,{credentials:`same-origin`,signal:e.signal});if(n.status===404||n.status===405)return e;if(!n.ok)return n;let r=(await n.json())?.key;if(typeof r!=`string`)throw Error(`The server sent an invalid upload key`);let i=new Headers(e.headers);return i.set(m,`1`),{...e,headers:i,body:await T(e.body,Uint8Array.fromBase64(r,{alphabet:`base64url`}),e.signal)}}async function N(e,t,n){let r=null;if(e!==`/api/admin/deduplication`&&t.body.size>A){let i=await n(`/api/config`,{credentials:`same-origin`,signal:t.signal});if(!i.ok)return i;let a=(await i.json()).managed,o=a?.uploadMaxBytes?.[e.endsWith(`/reports`)?`reports`:`bundles`];if(Number.isSafeInteger(o)&&o>0&&t.body.size>o)return Response.json({error:`too-large`},{status:413});let s=a?.uploadChunkBytes;Number.isSafeInteger(s)&&s>0&&s<=A&&(r=s)}let i=await M(t,n);return i instanceof Response?i:r==null||i.body.size<=A?await n(e,i):await F(e,i,n,r)}var P=3;async function F(e,t,n,r){let i=t.body,a=crypto.randomUUID(),o=e.endsWith(`/reports`)?`reports`:`bundles`,s=Math.ceil(i.size/r),c=new Headers(t.headers);c.set(`content-type`,`application/octet-stream`);let l=0,u=!1;try{let d=null,f=!1,p=(await Promise.allSettled(Array.from({length:Math.min(P,s)},async()=>{for(;!f&&l<s;){let e=l++;try{let s=await n(`/api/admin/uploads/${o}/${a}/${e}`,{...t,headers:c,body:i.slice(e*r,(e+1)*r)});s.ok||(d??=s,f=!0)}catch(e){throw f=!0,e}}}))).find(e=>e.status===`rejected`);if(p)throw p.reason;if(d)return d;let m=new Headers(t.headers);m.set(`x-upload-id`,a),m.set(`x-upload-parts`,String(s)),m.set(`x-upload-size`,String(i.size));let h=await n(e,{...t,headers:m,body:``});return u=h.ok,h}finally{if(!u&&l>0){let e=new Headers(t.headers);e.set(`x-upload-parts`,String(l)),await n(`/api/admin/uploads/${o}/${a}`,{...t,method:`DELETE`,headers:e,body:void 0,signal:AbortSignal.timeout(1e4)}).catch(()=>{})}}}async function I(e){await e.json().then(e=>e?.error,()=>null)===`view-only`&&globalThis.document?.dispatchEvent(new CustomEvent(`managed-view-only`))}async function L(e,n){if(n?.signal?.throwIfAborted(),E)return ee(e,n);let r=D;async function i(e,n){if(r!==D)throw new DOMException(`Managed session changed`,`AbortError`);let i=t();if(i){if(new URL(e,globalThis.location.origin).origin!==globalThis.location.origin)throw Error(`Public workspace requests must be same-origin`);let t=new Headers(n?.headers);t.set(`x-deepview-share`,i.token),n={...n,headers:t,credentials:`omit`,redirect:`error`}}let a=await fetch(e,{...n,cache:`no-store`});if(r!==D)throw new DOMException(`Managed session changed`,`AbortError`);return a.status===403&&![`GET`,`HEAD`].includes((n?.method??`GET`).toUpperCase())&&I(a.clone()),a}return n?.method===`POST`&&j.has(e)&&n.body instanceof Blob?await N(e,n,i):await i(e,n)}var R=new class{constructor(e=()=>{}){this.resources=new Map,this.session=null,this.teamCatalog=null,this.reportCatalog=null,this.bundleCatalog=null,this.generation=0,this.sessionController=new AbortController,this.notify=e}setSession(e){(this.session?.id!==e?.id||this.session?.role!==e?.role)&&this.reset(),this.session=e}reset(){this.generation++,this.sessionController.abort(),this.sessionController=new AbortController,this.invalidate(),this.session=null,this.teamCatalog=null,this.reportCatalog=null,this.bundleCatalog=null}setReportCatalog(e){let t=new Set,n=new Map(e.map(e=>[e.id,JSON.stringify([e.cacheKey??null,e.reports.map(e=>[e.id,e.cacheKey??null,e.visible!==!1]).toSorted(),(e.bundles??[]).map(e=>[e.id,e.filename,e.repoFullName,e.repoDirectory??``]).toSorted()])]));for(let e of new Set([...this.teamCatalog?.keys()??[],...n.keys()]))this.teamCatalog?.get(e)!==n.get(e)&&t.add(`team:${e}`);for(let e of this.resources.keys())if(e.startsWith(`reports:content:team:`)){let[t]=e.slice(21).split(`:`);(!n.has(t)||this.teamCatalog?.get(t)!==n.get(t))&&this.invalidate([e])}this.teamCatalog=n;let r=new Map;for(let t of e)for(let e of t.reports){let n=r.get(e.id)??[];n.push(JSON.stringify([t.id,e.cacheKey??null])),r.set(e.id,n)}let i=new Map([...r].map(([e,t])=>[e,JSON.stringify(t.toSorted())])),a=this.reportCatalog;this.reportCatalog=i;let o=new Set(t);for(let e of new Set([...a?.keys()??[],...i.keys()]))a?.get(e)!==i.get(e)&&o.add(e);for(let e of this.resources.keys()){if(!e.startsWith(`reports:content:`)||e.startsWith(`reports:content:team:`))continue;let t=e.slice(16);(!i.has(t)||o.has(t))&&(this.invalidate([e]),o.add(t))}let s=new Map;for(let t of e)for(let e of t.bundles??[]){let n=s.get(e.id)??[];n.push(JSON.stringify([t.id,t.cacheKey??null,e.filename,e.repoFullName,e.repoDirectory??``])),s.set(e.id,n)}let c=!1,l=new Map([...s].map(([e,t])=>[e,JSON.stringify(t.toSorted())]));for(let e of new Set([...this.bundleCatalog?.keys()??[],...l.keys()]))this.bundleCatalog?.get(e)!==l.get(e)&&(c=!0,o.add(`bundle:${e}`),this.invalidate([`bundle-metadata:${e}`]));this.bundleCatalog=l;for(let e of this.resources.keys()){if(!e.startsWith(`report-sources:`)&&!e.startsWith(`finding-history:`))continue;let[,n,r]=e.split(`:`);(n?t.has(`team:${n}`):c||o.has(r))&&this.invalidate([e])}return o}read(e){return this.resources.get(e)?.data}invalidate(e){for(let[t,n]of this.resources)e&&!e.some(e=>t===e||t.startsWith(`${e}:`))||(n.controller?.abort(),this.resources.delete(t))}async mutate(e,t){let n=this.generation,r;try{r=await e()}catch(e){throw n===this.generation&&e?.name!==`AbortError`&&this.notify(`Couldn't save changes: ${e?.message??e}`),e}if(n!==this.generation)throw new DOMException(`Managed session changed`,`AbortError`);return this.invalidate(t),r}async load(e,t,n,{signal:r,apply:i=()=>{},retryInvalidated:a=!1}={}){let o=this.generation;for(;;){r?.throwIfAborted();let s=this.resources.get(e);if(s||(s={},this.resources.set(e,s)),s.data!==void 0&&i(s.data),!s.pending){let e=s.controller=new AbortController;s.pending=(async()=>{try{let t=await n(e.signal);return e.signal.throwIfAborted(),s.data=t,t}catch(n){throw!e.signal.aborted&&n?.name!==`AbortError`&&this.notify(`Couldn't refresh ${t}: ${n?.message??n}`),n}})().finally(()=>{s.pending=null})}try{let t=await s.pending;if(r?.throwIfAborted(),this.resources.get(e)!==s)throw new DOMException(`Managed data changed`,`AbortError`);return i(t),t}catch(t){if(!a||t?.name!==`AbortError`||r?.aborted||o!==this.generation||this.resources.get(e)===s)throw t}}}}(e=>{document.dispatchEvent(new CustomEvent(`managed-notice`,{detail:{message:e}}))});function z(e){R.setSession(e)}function B(e){return R.setReportCatalog(e)}function V(){R.reset()}async function H(e,t=null,n={}){let r;try{r=await L(e,{credentials:`same-origin`,headers:{accept:`application/json`},...n})}catch{return t}if(r.status===401||r.status===403)return null;if(!r.ok)return t;try{return await r.json()}catch{return t}}async function U({fallback:e=null,sent:r}={}){let i=t()||O()!==null?void 0:await r;if(i===null)return null;let a=W(i);if(a!==void 0)return a;let o;try{let r=t(),i=await L(r?n(r):`/api/auth/session`,{credentials:`same-origin`,headers:{accept:`application/json`}});if(i.status===401||i.status===403)return null;if(!i.ok)return e;o=await i.json()}catch{return e}let s=W(o);return s===void 0?e:s}function W(e){let n=e?.user;if(n===null)return null;if(n!==void 0&&typeof n.login==`string`)return{id:n.id,login:n.login,name:typeof n.name==`string`?n.name:null,avatarUrl:typeof n.avatarUrl==`string`?n.avatarUrl:null,role:typeof n.role==`string`?n.role:`none`,csrfToken:typeof e.csrfToken==`string`?e.csrfToken:null,...t()?{publicShare:!0}:{},...typeof e.viewer?.login==`string`?{viewer:{id:e.viewer.id,login:e.viewer.login,name:typeof e.viewer.name==`string`?e.viewer.name:null}}:{},...!t()&&e.dependencyReview===!0?{dependencyReview:!0}:{}}}function G(e){let t=t=>Number.isSafeInteger(e?.[t])&&e[t]>=0;return e?.appMode===!1?{appMode:!1,...t(`appReports`)&&{appReports:e.appReports},...t(`findings`)&&{findings:e.findings}}:e?.appMode===!0&&t(`appFindings`)?{appMode:!0,appFindings:e.appFindings}:null}function te(e){if(typeof e?.sha!=`string`||typeof e.github!=`string`||!Array.isArray(e.tags))return null;let t=e.details,n=e=>typeof e==`string`?e:null,r=e=>Number.isSafeInteger(e)?e:null;return{sha:e.sha,github:e.github,tags:e.tags.filter(e=>typeof e==`string`),details:typeof t?.subject==`string`?{subject:t.subject,authorName:n(t.authorName),authorLogin:n(t.authorLogin),authoredAt:r(t.authoredAt),committedAt:r(t.committedAt)}:null}}async function K({fallback:e=[],signal:r,onRevision:i}={}){let a=t(),o=a?await H(n(a),null,{signal:r}):null,s=a?{teams:o?.team?[o.team]:[]}:await H(`/api/teams`,{teams:e},{signal:r}),c=s?.teams;return Array.isArray(c)?(i?.(typeof s.revision==`string`?s.revision:null),c.filter(e=>e!=null&&typeof e.id==`string`&&typeof e.name==`string`).map(e=>({id:e.id,slug:e.slug,name:e.name,...!a&&e.dependencyReview===!0?{dependencyReview:!0}:{},...e.permissions?{permissions:{dependencies:e.permissions.dependencies===!0,security:e.permissions.security===!0}}:{},...typeof e.cacheKey==`string`?{cacheKey:e.cacheKey}:{},...G(e.app)?{app:G(e.app)}:{},repos:Array.isArray(e.repos)?e.repos.filter(e=>Number.isSafeInteger(e?.repoId)&&e.repoId>0&&typeof e.fullName==`string`).map(e=>({repoId:e.repoId,fullName:e.fullName,path:typeof e.path==`string`&&e.path?e.path:null})):[],reports:Array.isArray(e.reports)?e.reports.filter(e=>e!=null&&typeof e.id==`string`&&typeof e.filename==`string`).map(e=>({id:e.id,slug:e.slug,filename:e.filename,visible:e.visible!==!1,...e.analyzer===null||typeof e.analyzer==`string`?{analyzer:e.analyzer}:{},repoFullName:typeof e.repoFullName==`string`?e.repoFullName:``,repoDirectory:typeof e.repoDirectory==`string`?e.repoDirectory:``,...typeof e.cacheKey==`string`?{cacheKey:e.cacheKey}:{}})):[],bundles:Array.isArray(e.bundles)?e.bundles.filter(e=>e!=null&&typeof e.id==`string`&&typeof e.filename==`string`).map(e=>({id:e.id,slug:e.slug,integrity:e.integrity,byteSize:e.byteSize,repoId:e.repoId,filename:e.filename,kind:e.kind,visible:e.visible!==!1,summary:e.summary??null,summaryRetryAt:Number.isSafeInteger(e.summaryRetryAt)&&e.summaryRetryAt>0?e.summaryRetryAt:null,repoDirectory:typeof e.repoDirectory==`string`?e.repoDirectory:``,repoFullName:typeof e.repoFullName==`string`?e.repoFullName:``,commitInfo:te(e.commitInfo)})):[]}))):s==null?[]:e}function q(e){return e?.links===void 0?[]:Array.isArray(e.links)&&e.links.every(e=>Array.isArray(e)&&e.length>=2&&e.every(e=>typeof e==`string`))?e.links:null}function J(e){return s(e?.data)===null||typeof e.repo?.directory!=`string`||e.repo.github!==null&&typeof e.repo.github!=`string`||q(e)===null?null:{data:e.data,repo:e.repo,...e.links?{links:e.links}:{}}}async function Y(e,{signal:t}={}){return J(await H(`/api/reports/${encodeURIComponent(e)}`,null,{signal:t}))}async function X(e,{signal:t}={}){let n=[...new Set(e)];if(n.length===0)return[];let r=await H(`/api/reports/query`,null,{method:`POST`,signal:t,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify({ids:n})});if(!Array.isArray(r?.reports)||r.reports.length!==n.length)return null;let i=new Map;for(let e of r.reports){let t=J(e);if(!t||!n.includes(e.id)||i.has(e.id))return null;i.set(e.id,t)}let a=q(r);return a===null?null:e.map(e=>({...i.get(e),...a.length>0?{links:a}:{}}))}async function Z(e,{signal:t,reportId:n=null,lite:r=!1}={}){let i=new URLSearchParams(n===null?{}:{reportId:n});r&&i.set(`lite`,`1`);let a=await H(`/api/teams/${encodeURIComponent(e)}/reports${i.size>0?`?${i}`:``}`,null,{signal:t});if(!Array.isArray(a?.reports))return null;let o=[],s=new Set;for(let e of a.reports){let t=J(e);if(!t||typeof e.id!=`string`||typeof e.filename!=`string`||s.has(e.id))return null;s.add(e.id),o.push({id:e.id,filename:e.filename,...t})}let c=q(a);return c===null?null:(Object.defineProperty(o,"links",{value:c}),a.folded===!0&&Object.defineProperty(o,"folded",{value:!0}),o)}function Q(e){return e?`?team=${encodeURIComponent(e)}`:``}async function ne(e,{reportId:t,...n}={}){let r=t==null?``:`?reportId=${encodeURIComponent(t)}`,i=await H(`/api/teams/${encodeURIComponent(e)}/annotations${r}`,null,n),{reports:a,entries:o,comments:s,issues:c={}}=i??{};if(!a||typeof a!=`object`||Array.isArray(a)||!o||typeof o!=`object`||Array.isArray(o)||!Array.isArray(s)||!c||typeof c!=`object`||Array.isArray(c)||Object.values(a).some(e=>!Array.isArray(e)||e.some(e=>typeof e!=`string`))||s.some(e=>!e||typeof e.findingId!=`string`))return null;let l=new Map;for(let[e,t]of s.entries()){let n=t.findingId,r=l.get(n)??[];r.push(e),l.set(n,r)}let u=new Map,d=new Map,f=typeof i.revision==`string`?i.revision:null;return Object.assign(e=>{if(!Object.hasOwn(a,e))return null;if(d.has(e))return d.get(e);let t=JSON.stringify(a[e]),n=u.get(t);if(!n){let r=[...new Set(a[e])],i=r.flatMap(e=>l.get(e)??[]);n={entries:Object.fromEntries(r.filter(e=>Object.hasOwn(o,e)).map(e=>[e,o[e]])),comments:i.toSorted((e,t)=>e-t).map(e=>s[e]),issues:Object.fromEntries(r.filter(e=>Object.hasOwn(c,e)).map(e=>[e,c[e]]))},u.set(t,n)}return d.set(e,n),n},{revision:f})}async function re(e,t,n){let r=(await H(`/api/reports/${encodeURIComponent(e)}/triage${Q(t)}`,null,n))?.entries;return typeof r==`object`&&r&&!Array.isArray(r)?r:null}async function ie(e,n,r=null){if(t())return[];let i=r===null?``:`?reportId=${encodeURIComponent(r)}`,a=await H(`/api/teams/${encodeURIComponent(e)}/fixes${i}`,null,{signal:n});return Array.isArray(a?.fixes)?a.fixes:null}async function ae(e,t,n){let r=await H(`/api/reports/${encodeURIComponent(e)}/comments${Q(t)}`,null,n);return Array.isArray(r?.comments)?r.comments:null}async function oe(e,{findingId:t,body:n,commentId:r=null,version:i},a,o){let s=r==null?``:`/${encodeURIComponent(r)}`;try{let c=await L(`/api/reports/${encodeURIComponent(e)}/comments${s}${Q(o)}`,{method:r==null?`POST`:`PATCH`,credentials:`same-origin`,headers:{"content-type":`application/json`,...a?{"x-csrf-token":a}:{}},body:JSON.stringify(r==null?{findingId:t,body:n}:{body:n,version:i})});return{status:c.status,comment:c.ok?(await c.json()).comment:null}}catch{return{status:0,comment:null}}}async function $(e,t,n,r,i){try{return(await L(`/api/reports/${encodeURIComponent(e)}/comments/${encodeURIComponent(t)}${Q(i)}`,{method:`DELETE`,credentials:`same-origin`,headers:{"content-type":`application/json`,...r?{"x-csrf-token":r}:{}},body:JSON.stringify({version:n})})).status}catch{return 0}}async function se(e,t,n,r){try{return(await L(`/api/reports/${encodeURIComponent(e)}/triage${Q(r)}`,{method:`POST`,credentials:`same-origin`,headers:{"content-type":`application/json`,...n?{"x-csrf-token":n}:{}},body:JSON.stringify({entries:t})})).status}catch{return 0}}function ce(e){e&&(location.href=e)}async function le(e){if(t()){location.href=`/`;return}try{await L(`/api/auth/logout`,{method:`POST`,credentials:`same-origin`,headers:e?{"x-csrf-token":e}:{}})}catch{}location.reload()}async function ue(e,t){let n=await L(`/api/auth/view-as`,{method:`POST`,credentials:`same-origin`,headers:{"content-type":`application/json`,...t?{"x-csrf-token":t}:{}},body:JSON.stringify({userId:e})});if(!n.ok)throw Error(`HTTP ${n.status}`);location.assign(`/`)}async function de(e){try{await L(`/api/auth/view-as`,{method:`DELETE`,credentials:`same-origin`,headers:e?{"x-csrf-token":e}:{}})}catch{}location.assign(o[`admin-users`])}async function fe(e){let t=await L(`/api/teams/${encodeURIComponent(e)}/share`,{credentials:`same-origin`});if(!t.ok)throw Error(`Could not load public links (${t.status})`);return(await t.json()).shares}async function pe(e,t,{id:n,revoke:r=!1,dependencies:i=!1,security:a=!1}={}){let o=n?`/${encodeURIComponent(n)}`:``,s=await L(`/api/teams/${encodeURIComponent(e)}/share${o}`,{method:r?`DELETE`:n?`PATCH`:`POST`,credentials:`same-origin`,headers:{"x-csrf-token":t,"content-type":`application/json`},...r?{}:{body:JSON.stringify({dependencies:i,security:a})}});if(!s.ok)throw Error(`Could not ${r?`revoke`:n?`update`:`create`} public link (${s.status})`);return s.json()}async function me(e,t){let n=await L(`/api/bundles/${encodeURIComponent(e)}/download`,{credentials:`same-origin`});if(!n.ok)throw Error(`Could not download bundle (${n.status})`);let r=URL.createObjectURL(await n.blob()),i=document.createElement(`a`);i.href=r,i.download=t,i.click(),setTimeout(()=>URL.revokeObjectURL(r),6e4)}export{u as a,O as b,k as c,L as d,R as e,z as f,B as g,V as h,U as i,K as j,Y as k,X as l,Z as m,Q as n,ne as o,re as p,ie as q,ae as r,oe as s,$ as t,se as u,ce as v,le as w,ue as x,de as y,fe as z,pe as A,me as B};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{Ve as e,Xe as t,Ze as n,a as r,ua as i,w as a}from"./chunk-IPAH4LKF.js";import{c as o,d as s,g as c}from"./chunk-2XUEZHIP.js";var l=e(s`<path d="M3.5 8.4l2.9 2.9 6.1-6.6"/>`),u=e(s`<circle class="fill" cx="8" cy="8" r="3"/>`),d=e(s`<path d="M4.2 4.2l7.6 7.6M11.8 4.2l-7.6 7.6"/>`),f=e(s`<circle class="dotted" cx="8" cy="8" r="5.5"/>`),p=e(s`<path d="M2.6 3.2h7.6v5.3H6.3L4 10.4V8.5H2.6z"/><path d="M12.2 6.2h1.2v5.3H12v1.9l-2.3-1.9H7"/>`),m={approved:[`approved`,n.approved[1],`Approved`],changes:[`changes`,n.changes[1],`Changes requested`],commented:[`commented`,t,`Commented`],dismissed:[`dismissed`,t,`Review dismissed`]},h={done:[`reviewed`,l,`Reviewed`],running:[`running`,u,`Reviewing`],failed:[`failed`,d,`Review failed`],requested:[`requested`,f,`Asked to review again`]},g=[`requested`,f,`Review requested`],_=e=>e.slice(0,7),v=e=>new Date(e).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`}),y=(e,t,n=!1)=>`${e.toLocaleString(`en-US`)}${n?`+`:``} ${t}${e===1&&!n?``:`s`}`;function b(e){return e?e.failed?h.failed:e.requested?h.requested:h[e.code?.status]??null:null}function x(e){let t=b(e.codex),n=e.codex?.code?.commit??null;return[...t?[{who:i(e.codex.login,`Codex`),standing:t,commit:n,stale:n!==null&&n!==e.head}]:[],...e.reviewers.map(t=>({who:i(t.login,t.login??`someone`),standing:m[t.state]??g,requested:t.requested&&!!m[t.state],workflow:t.workflow??null,commit:t.commit,at:t.at,stale:t.commit!==null&&t.commit!==e.head}))]}var S=e=>(e.moreReviews??0)+(e.moreRequests??0),C=e=>[e.moreReviews>0?y(e.moreReviews,`more review`):null,e.moreRequests>0?y(e.moreRequests,`more review request`):null].filter(Boolean).join(` and `);function w(e){if(!e.head)return!0;let t=e.codex?.code;return t?.status===`done`&&t.commit===e.head||e.reviewers.some(t=>m[t.state]&&t.state!==`dismissed`&&t.commit===e.head)?!0:e.moreReviews>0&&null}var T=e=>e?o`<span class="${`review-severity is-${e}`}">${e.toUpperCase()}</span>`:c;function E(e){if(!e)return c;let t=x(e),{open:n,more:r,severity:i}=e.threads,a=n>0?`${y(n,`open review thread`,r)}${i?`, the gravest ${i.toUpperCase()}`:``}`:r?`No open review thread among those read; more on GitHub`:null,s=w(e);return o`<span class="issue-reviews">${t.map(({who:e,standing:[t,n,r],commit:i,stale:a,requested:s})=>{let c=`${r}${s?`, and requested again`:``}${a?`, on an earlier commit (${_(i)})`:i?`, on the latest commit`:``}`;return o`<span class="${`review-mark is-${t}${a?` is-stale`:``}`}"><span class="review-glyph" role="img" aria-label="${c}" data-tooltip="${c}">${n}</span><span class="review-who">${e}</span></span>`})} ${S(e)>0?o`<span class="review-more" data-tooltip="${`${C(e)}, on GitHub`}">+${S(e)}</span>`:c} ${a?o`<span class="review-threads" role="img" aria-label="${a}" data-tooltip="${a}">${p}<span>${n}${r?`+`:``}</span>${T(i)}</span>`:c} ${s===!1?o`<span class="review-unreviewed" data-tooltip="${t.length>0?`No review is on the latest commit`:`No reviews yet`}">Unreviewed</span>`:s===null?o`<span class="review-unreviewed" data-tooltip="No review read is on the latest commit; more on GitHub">Unreviewed?</span>`:c}</span>`}function D(e,t,n){if(!e)return c;let r=o`<code>${_(e)}</code>`;return o`<span class="review-on">on ${n?o`<a href="${`https://github.com/${n}/commit/${e}`}" target="_blank" rel="noopener noreferrer">${r}</a>`:r}${e===t?`, the latest commit`:`, an earlier commit`}</span>`}function O(e,t){if(!e)return c;let{head:n,codex:r}=e,a=(e,[a,s,c],l)=>o`<li class="review-row">${i(r.login,`Codex`)} <span class="${`review-state is-${a}`}">${s}${l}: ${c.toLowerCase()}</span>${D(e.commit,n,t)}</li>`,s=[...r?.code?[a(r.code,b(r)??h.done,`Code review`)]:[],...r?.security?[a(r.security,h[r.security.status]??h.done,`Security review`)]:[],...x({...e,codex:null}).map(({who:e,standing:[r,i,a],commit:s,at:l,requested:u,workflow:d})=>o`<li class="review-row">${e} <span class="${`review-state is-${r}`}">${i}${a}${u?`, requested again`:``}</span>${d?o`<span class="review-on">by the workflow <code>${d}</code></span>`:c}${D(s,n,t)}${l?o`<time datetime="${new Date(l).toISOString()}">${v(l)}</time>`:c}</li>`)],{open:l,resolved:u,more:d,list:f=[]}=e.threads;return o`<section class="repo-item-section"><h4>Reviews</h4>${s.length>0?o`<ul>${s}</ul>`:o`<p class="repo-item-quiet">No reviews yet.</p>`} ${S(e)>0?o`<p class="repo-item-quiet">And ${C(e)}, on GitHub.</p>`:c} ${w(e)===null?o`<p class="repo-item-quiet">No review read is on the latest commit, <code>${_(n)}</code>; one of those on GitHub may be.</p>`:s.length>0&&!w(e)?o`<p class="repo-item-quiet">No review is on the latest commit, <code>${_(n)}</code>.</p>`:c}</section>${l>0||u>0?o`<section class="repo-item-section"><h4>Open threads</h4>${f.length>0?o`<ul>${f.map(e=>o`<li><a class="repo-item-row review-thread" href="${e.url??c}" target="_blank" rel="noopener noreferrer">${T(e.severity)}<span class="repo-item-title">${e.title||`(no comment)`}</span> ${e.path?o`<code class="review-path">${e.path}${e.line?`:${e.line}`:``}</code>`:c} ${e.outdated?o`<span class="repo-item-quiet">outdated</span>`:c}</a></li>`)}</ul>`:o`<p class="repo-item-quiet">${d?`None open among those read.`:`None open.`}</p>`} ${u>0||d?o`<p class="repo-item-quiet">${u>0?`${y(u,`thread`)} resolved`:``}${d?`${u>0?`; `:``}more on GitHub`:``}.</p>`:c}</section>`:c}`}var k=r({items:new Map,changes:0}),A=null,j=()=>a.managedSession?`${a.managedSession.id}\0${a.managedSession.role}`:null,M=(e,t,n)=>`${e}\0${t}\0${n}`,N=e=>Number.isSafeInteger(e?.readAt)&&e.readAt>0?e.readAt:Date.now();function P(e,t,n,r=null){let i=j();i!==A&&(k.items.clear(),A=i);let a=!1;for(let o of t){let t=M(i,e,o.number),s=k.items.get(t);if(s&&s.readAt>n)continue;let c=s&&(s.item.state===`open`?`open`:`closed`),l=!c||c===(o.state===`open`?`open`:`closed`)?s?.moved??null:{from:c,before:s.readAt};k.items.set(t,{item:{...o,kind:o.kind??r??s?.item.kind??null},readAt:n,moved:l}),a=!0}a&&k.changes++}var F=(e,t)=>k.items.get(M(j(),e,t))??null;function I(e,t){let n=M(j(),e,``);return k.changes,[...k.items].flatMap(([e,r])=>e.startsWith(n)&&r.item.kind===t?[r]:[])}var L=()=>k.changes,R=e=>e.state===`open`?`open`:`closed`;function z(e,t){let n=R(e.item);if(e.readAt<=t||!e.moved)return n;if(e.moved.before>=t)return e.moved.from;let r=e.item.closedAt??e.item.mergedAt??null;return n===`closed`&&r!==null&&r>t?e.moved.from:n}export{E as a,O as b,N as c,P as d,F as e,I as f,L as g,R as h,z as i};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as e,c as t}from"./chunk-GDPCLSOS.js";import{g as n,n as r,r as i,s as a,t as o,u as s,v as c,w as l,x as u}from"./chunk-
|
|
1
|
+
import{a as e,c as t}from"./chunk-GDPCLSOS.js";import{g as n,n as r,r as i,s as a,t as o,u as s,v as c,w as l,x as u}from"./chunk-KOGNQDSJ.js";import{a as d}from"./chunk-NRPC74AM.js";import{e as f,i as p}from"./chunk-7C7DWL7I.js";import"./chunk-PNHBZGDD.js";import"./chunk-2K6UN3PC.js";import"./chunk-HT2SSA3V.js";import{D as m}from"./chunk-SXV2T5C4.js";import"./chunk-WFYLMF6Z.js";import"./chunk-C4Z6ZBXV.js";import{a as h,c as g,g as _}from"./chunk-2XUEZHIP.js";import"./chunk-TUII34K2.js";import"./chunk-OOJM4CTU.js";var v=`h1{font-size:1.35rem;margin-bottom:.5rem}h2{font-size:1.1rem;margin-bottom:.5rem}.triage-import{display:flex;gap:1rem;align-items:center;margin:1.5rem 0 2rem}.triage-import .btn{flex-shrink:0}.triage-import p{margin:0}.workspace-drop{display:grid;gap:.8rem;padding:2rem;margin:1.5rem 0;border:1px dashed var(--border);border-radius:var(--ui-radius, 8px)}.workspace-drop.dragging{border-color:var(--accent);background:rgb(from var(--accent) r g b / .08)}.workspace-drop span,p,li span{color:var(--muted);line-height:1.5}.actions,.local-choice{display:flex;gap:.8rem;flex-wrap:wrap;align-items:center}.local-choice{margin-bottom:1.5rem}.import-preview{display:grid;gap:.8rem}input:not([type=radio]),select{padding:.55rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);color:var(--text);background:var(--bg);font:inherit}.import-preview input:not([type=radio]),.import-preview select{width:100%;box-sizing:border-box}fieldset{display:grid;gap:.8rem;padding:1rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px)}fieldset label{display:flex;gap:.5rem;align-items:center}li{padding:.4rem 0;overflow-wrap:anywhere}li span{display:block;font-size:.8rem}ul{padding-left:1.2rem}.primary{justify-self:start;color:var(--accent)}.error{color:var(--critical)}button:disabled{opacity:.5}input:focus-visible,select:focus-visible,button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
|
2
2
|
`;async function y(e,{session:t,confirmImport:n,...r}){if(t?.role!==`admin`||!t.csrfToken)throw Error(`An administrator session is required.`);if(e!=null&&(typeof e!=`object`||Array.isArray(e)))throw Error(`Invalid local triage.`);let i=Object.create(null);for(let[t,n]of Object.entries(e??{})){let{ignoredReports:e,scopedIgnoredReports:r,...a}=f(n)??{};Object.keys(a).length!==0&&(i[t]=a)}let a=Object.keys(i).length,o=new Set,s=[],c;if(a>0)do{r.signal?.throwIfAborted();let e=`/api/admin/reports/finding-ids`+(c?`?after=${encodeURIComponent(c)}`:``),{reports:t,nextCursor:n}=await r.api.send(e);r.signal?.throwIfAborted();for(let e of t){let t=e.findingIds.filter(e=>Object.hasOwn(i,e)&&!o.has(e));t.length>0&&s.push({id:e.id,ids:t});for(let e of t)o.add(e)}c=n}while(c);for(let e of o){if(!e||e.length>100)throw Error(`Triage finding IDs must be between 1 and 100 characters.`);if(u(i[e])===`invalid`)throw Error(`Triage for ${e} exceeds the managed server limits.`)}if(r.signal?.throwIfAborted(),n){let e=await n({matched:o.size,available:a});if(r.signal?.throwIfAborted(),!e)return null}let l=r.importedIds??new Set;for(let e of s)await C(i,{...r,importedIds:l,ids:e.ids,path:`/api/admin/reports/${encodeURIComponent(e.id)}/import-triage`});return o.size}function b(e,t){let n=[],r=Object.create(null);for(let[i,a]of Object.entries(e)){let e=t[i];if(!e)throw Error(`The server did not return the requested triage snapshot.`);let o=e.entry??{},s=r[i]={...o};delete s.comment;for(let[t,r]of Object.entries(a))if(t===`comment`){if(e.comments.some(e=>e.body===r))continue;e.comments.length>0?n.push({id:i,property:t,local:e.comments.map(e=>e.body).join(`
|
|
3
3
|
|
|
4
4
|
`),imported:r}):s.comment=r}else if(o[t]!==void 0&&o[t]!==r){let e=e=>t===`flagged`?e?`flagged`:`not flagged`:e;n.push({id:i,property:t,local:e(o[t]),imported:e(r)})}else s[t]=r}return{entries:r,conflicts:n}}async function x(e,t,n,r,i){i?.throwIfAborted();let{entries:a,conflicts:o}=b(e,t);if(o.length===0)return a;let s=await r(o,n,{title:`Triage conflicts on import`,intro:`disagree with stored triage on`,trailingNote:`Imported comments are added alongside existing comments. Other choices apply to these finding IDs across all teams.`,importedSideLabel:`Apply imported`});if(i?.throwIfAborted(),!s)throw Object.assign(Error(`Triage conflict resolution was cancelled.`),{cancelled:!0});for(let t of o){let n=s[`${t.id}:${t.property}`];if(![`local`,`imported`].includes(n))throw Error(`Resolve every triage conflict before importing.`);n===`imported`&&(a[t.id][t.property]=e[t.id][t.property])}return a}function S(e,t){let n=[],r={entries:{},expected:{}};for(let[i,a]of Object.entries(e)){let e={entries:{...r.entries,[i]:a},expected:{...r.expected,[i]:t[i].version}};if(new TextEncoder().encode(JSON.stringify(e)).length<=262144){r=e;continue}if(Object.keys(r.entries).length===0)throw Error(`This triage entry is too large to import.`);n.push(r),r={entries:{[i]:a},expected:{[i]:t[i].version}}}return Object.keys(r.entries).length>0&&n.push(r),n}async function C(e,{api:t,path:n,ids:r=Object.keys(e),importedIds:i=new Set,lookup:a=new Map,resolveConflicts:o,signal:s}){r=r.filter(t=>Object.hasOwn(e,t)&&!i.has(t));for(let c=0;c<r.length;c+=200){let l=r.slice(c,c+200);for(let r=0;r<5&&l.length>0;r++){s?.throwIfAborted();let{snapshots:r}=await t.send(n,{findingIds:l}),c=await x(Object.fromEntries(l.map(t=>[t,e[t]])),r,a,o,s);for(let e of S(c,r)){if(s?.throwIfAborted(),(await t.send(n,e)).conflict)break;Object.keys(e.entries).forEach(e=>i.add(e))}l=l.filter(e=>!i.has(e))}if(l.length>0)throw Error(`Stored triage keeps changing. Retry to resolve it against the latest values.`)}}var w=`You can retry the remaining steps.`;function T(e){return String(e?.detail??e?.message??e).replace(/\.$/u,``)}function E(e,t){return t?.aborted===!0||e?.name===`AbortError`||e?.cancelled===!0}function D(e){if(typeof e!=`string`)return{ok:!0,path:null};if(/\p{Cc}/u.test(e)||e.includes(`\\`)||e!==e.trim())return{ok:!1};let t=[];for(let n of e.split(`/`))if(n!==``&&n!==`.`){if(n===`..`||n!==n.trim())return{ok:!1};t.push(n)}let n=t.join(`/`);return n.length>500?{ok:!1}:{ok:!0,path:n===``?null:n}}async function O(e,t){let n=new Uint8Array(await e.arrayBuffer());return r(n)?t({tryPassword:e=>i(n,e)}):n[0]===31&&n[1]===139?i(n):a(new TextDecoder(`utf-8`,{fatal:!0}).decode(n))}function k(e,t,n,r,i=``){let a=e?d(e,t,r,i):null,o=n.find(t=>a?t.repoId===a.repoId:t.fullName.toLowerCase()===e?.toLowerCase());return{repoId:o?.repoId??null,directory:a?.directory??t,github:o?.fullName??e}}async function A(e,t,r=[]){let i=new Map,a=[];for(let n of e.reports){if(typeof n?.name!=`string`||!n.name||typeof n.content!=`string`)throw Error(`Every report must have a name and content.`);let u=o(n.content,n.name);if(!u.data)throw Error(`${n.name}: ${u.reason??`Unsupported report`}`);let d=m(u.data),f=d??m(n)??m({repo:{github:e.repoUrls?.[n.name]}})??c(u.data),p=d?``:l(u.data),h=D(u.data.repo?.directory);if(!h.ok)throw Error(`${n.name}: invalid repository directory`);let g=u.format===`links`?[]:(await s(n.content,n.name))?.findings??[];for(let e of g)e.id&&i.set(e.id,e);let _=h.path??``;a.push({...n,links:u.format===`links`,...k(f,_,t,r,p),declaredGithub:f,declaredDirectory:_,filePrefix:p,embedded:d,ids:[...new Set(g.map(e=>e.id).filter(Boolean))],uploaded:null})}let u=Object.create(null);if(e.triage!=null&&(typeof e.triage!=`object`||Array.isArray(e.triage)))throw Error(`Invalid workspace triage.`);let d=await n(e.triage,t=>e.reports.find(e=>e.name===t)?.content);for(let[e,t]of Object.entries(d.entries)){if(!i.has(e))continue;let n=f(t);if(!n)continue;let{ignoredReports:r,scopedIgnoredReports:a,...o}=n;Object.keys(o).length!==0&&(u[e]=o)}let p=[];for(let t of e.bundleBlobs??[]){let e=Uint8Array.fromBase64(t.data),n=`sha512-${new Uint8Array(await crypto.subtle.digest(`SHA-512`,e)).toBase64()}`;if(n!==t.integrity)throw Error(`${t.name}: bundle integrity mismatch`);p.push({name:t.name,integrity:n,bytes:e,uploaded:null})}return{name:e.workspace.name.slice(0,100),reports:a,bundles:p,triage:u,lookup:i,references:e.bundles??[],team:null,completed:new Set,importedIds:new Set}}function j(e,t,n){async function r(r,i,a={}){n?.throwIfAborted();let o=await e(r,{credentials:`same-origin`,signal:n,...i===void 0?{}:{method:`POST`,body:i instanceof File?i:JSON.stringify(i)},headers:{...i instanceof File?{}:{"content-type":`application/json`},"x-csrf-token":t.csrfToken,...a}});if(n?.throwIfAborted(),o.status===409)return{conflict:!0};if(!o.ok){let e=await o.json().then(e=>typeof e?.error==`string`?e.error:``,()=>``);n?.throwIfAborted();let t=`Import request failed (HTTP ${o.status}${e?`: ${e}`:``}).`;throw Object.assign(Error(`${t} ${w}`),{detail:t})}let s=await o.json();return n?.throwIfAborted(),s}return{send:r}}async function M(e,t,n,r,i,a){if(e.bundles.length===0&&e.references.length===0)return;let o=i??(await n.send(`/api/admin/bundles`)).bundles,s=new Set(e.bundles.map(e=>e.uploaded.id));if([...s].some(e=>!o.some(t=>t.id===e)))throw Error(`Could not verify the uploaded source bundles. Retry the import.`);let c=new Set(e.references);for(let i of o){if(!s.has(i.id)&&!c.has(i.integrity))continue;let o=!a.has(i.repoId),l=o?t:i.repoId;o&&await r(`bundle-repo:${i.id}:${l}`,()=>n.send(`/api/admin/bundles/set-repo`,{bundleId:i.id,repoId:l}));let u=o?``:i.repoDirectory??``;await r(`repo:${l}:${u}`,()=>n.send(`/api/admin/teams/set-repo`,{teamId:e.team.id,repoId:l,path:u}))}}async function N(e,t){e.uploaded||=await t.send(`/api/admin/deduplication`,new File([e.content],e.name),{"x-report-filename":encodeURIComponent(e.name)})}async function P(e,t){let n=(await t.send(`/api/admin/repositories/browsable`)).repos,r=e.reports.filter(e=>!e.links&&e.declaredGithub&&!e.uploaded);if(r.length>0){let{aliases:e=[]}=await t.send(`/api/admin/repositories/aliases`);for(let t of r)Object.assign(t,k(t.declaredGithub,t.declaredDirectory,n,e,t.filePrefix))}return new Set(n.map(e=>e.repoId))}async function F(e,{plan:t,api:n,step:r,activeRepos:i,defaultRepo:a,includeTriage:o,resolveConflicts:s,signal:c}){if(e.links){await N(e,n);return}let l=i.has(e.repoId)?e.repoId:a;if(!e.uploaded){let t=await n.send(`/api/admin/reports`,new File([e.content],e.name),{"x-report-filename":encodeURIComponent(e.name),"x-repo-id":String(l),"x-repo-directory":encodeURIComponent(e.directory)});if(t.conflict)throw Error(`Could not reuse the stored report ${e.name}. Retry the import.`);e.uploaded=t}let u=e.uploaded;i.has(u.repoId)||await r(`report-repo:${u.id}:${l}:${e.directory}`,async()=>{if((await n.send(`/api/admin/reports/set-repo`,{reportId:u.id,repoId:l,directory:e.directory})).conflict)throw Error(`Could not assign the stored report ${e.name} to its repository.`);u.repoId=l,u.repoDirectory=e.directory});let d=u.repoDirectory??``;await r(`repo:${u.repoId}:${d}`,()=>n.send(`/api/admin/teams/set-repo`,{teamId:t.team.id,repoId:u.repoId,path:d})),o&&await C(t.triage,{api:n,resolveConflicts:s,signal:c,ids:e.ids,importedIds:t.importedIds,lookup:t.lookup,path:`/api/admin/reports/${encodeURIComponent(e.uploaded.id)}/import-triage`}),await r(`publish:${e.uploaded.id}`,()=>n.send(`/api/admin/reports/set-visible`,{reportId:e.uploaded.id,visible:!0}))}async function I(e,{api:t,session:n,defaultRepo:r,includeTriage:i,resolveConflicts:a,signal:o,progress:s=()=>{}}){if(n?.role!==`admin`||!n.csrfToken)throw Error(`An administrator session is required.`);if(!e.name.trim()||e.name.trim().length>100)throw Error(`Enter a team name of up to 100 characters.`);if(i)for(let[t,n]of Object.entries(e.triage)){if(!t||t.length>100)throw Error(`Triage finding IDs must be between 1 and 100 characters. Choose Skip triage to import the files without it.`);if(u(n)===`invalid`)throw Error(`Triage for ${t} exceeds the managed server limits. Choose Skip triage to import the files without it.`)}o?.throwIfAborted();let c=null;if(e.bundles.length===0){let n=new Set(e.references);c=n.size>0?(await t.send(`/api/admin/bundles`)).bundles.filter(e=>n.has(e.integrity)):[]}if(e.reports.length===0&&e.bundles.length===0&&c.length===0)throw Error(e.references.length>0?`None of the referenced source bundles are available on the server. Export with bundle bytes included and try again.`:`This workspace contains no report or bundle files.`);let l=await P(e,t);for(let t of e.reports.filter(e=>!e.links)){if(t.embedded&&!l.has(t.repoId))throw Error(`Connect ${t.embedded} in Repositories before importing ${t.name}.`);if(!l.has(t.repoId)&&!l.has(r))throw Error(`Choose an active repository for ${t.name}.`)}if((e.bundles.length>0||c.some(e=>!l.has(e.repoId)))&&!l.has(r))throw Error(`Choose an active repository for the source bundles.`);let d=()=>o?.throwIfAborted(),f=async(t,n)=>{d(),e.completed.has(t)||(await n(),e.completed.add(t))};if(d(),!e.team){let n=await t.send(`/api/admin/teams`,{name:e.name.trim()});if(n.conflict)throw Error(`A team already has this name. Choose another name.`);e.team=n}await f(`member`,()=>t.send(`/api/admin/teams/set-member`,{teamId:e.team.id,userId:n.id,security:!0,dependencies:!0}));for(let n of e.bundles)d(),s(`Importing ${n.name}\u2026`),n.uploaded||=await t.send(`/api/admin/bundles`,new File([n.bytes],n.name),{"x-bundle-filename":encodeURIComponent(n.name)});await M(e,r,t,f,c,l);let p=[];for(let n of e.reports){d(),s(`Importing ${n.name}\u2026`);try{await F(n,{plan:e,api:t,step:f,activeRepos:l,defaultRepo:r,includeTriage:i,resolveConflicts:a,signal:o})}catch(e){if(E(e,o))throw e;p.push(`${n.name}: ${T(e)}`)}}if(p.length>0)throw Error(`Could not import ${p.length} of ${e.reports.length} files: ${p.join(`; `)}. ${w}`);return e.team}function L(e){let t=()=>e.isEncryptionEnabled()&&!e.isUnlocked();return{get locked(){return t()},unlock:t=>e.unlockEncryption(t),async read({signal:n}={}){let r=!1,i=e.onVaultStateChange(()=>{r=!0}),a=()=>{if(n?.throwIfAborted(),t()||r)throw Error(`Local data was locked or changed. Unlock it and import triage again.`)};try{a();let t=await e.readTriageBlob();return a(),t}finally{i()}}}}function R(e){let t=()=>e.isEncryptionEnabled()&&!e.isUnlocked();async function n(){let t=JSON.parse(await e.hydrateKey(`deepview.workspaces`)||`[]`);return(Array.isArray(t)?t:t.workspaces??[]).filter(e=>typeof e.id==`string`&&typeof e.name==`string`)}async function r(n,r){let i=!1,a=[e.onVaultStateChange,e.onFileMutated,e.onBundleMutated].map(e=>e(()=>{i=!0})),o=()=>{if(r?.throwIfAborted(),t()||i)throw Error(`Local data was locked or changed. Unlock it and select the workspace again.`)};try{o();let e=await n(o);return o(),e}finally{a.forEach(e=>e())}}return{get locked(){return t()},unlock:t=>e.unlockEncryption(t),list:({signal:e}={})=>r(async()=>(await n()).map(e=>({id:e.id,name:e.name})),e),read:(t,{signal:i}={})=>r(async r=>{let i=(await n()).find(e=>e.id===t);if(!i)throw Error(`This local workspace no longer exists.`);let a=JSON.stringify(i),o=JSON.parse(await e.hydrateKey(`deepview.repoUrls`)||`{}`),s=[];for(let t of i.reports??[]){r();let n=await e.withStoredItem(`report`,t,()=>e.readFile(t));r(),s.push({name:t,content:n,...o[t]?{repo:{github:o[t]}}:{}})}let c=await e.listBundles(),l=[];for(let t of i.bundles??[]){r();let n=c.find(e=>e.integrity===t);if(!n)continue;let i=await e.withStoredItem(`bundle`,t,()=>e.readBundle(t));r(),l.push({integrity:t,name:n.name,data:i.toBase64()})}let u=await e.readTriageBlob()??{};if(JSON.stringify((await n()).find(e=>e.id===t))!==a)throw Error(`The local workspace changed. Select it again.`);return{version:1,workspace:{id:t,name:i.name,privateKey:``},reports:s,bundles:i.bundles??[],bundleBlobs:l,triage:u,repoUrls:o}},i)}}var z=e=>e===`bundle`?`bundles`:`reports`,B=(e,t)=>JSON.stringify([e,t||``]),V=(e,t)=>new Set(t.map(t=>e===`bundle`?t.integrity:B(t.sha256,t.analyzer)));async function H(e){let t=new Uint8Array(await e.arrayBuffer()),n=o(new TextDecoder().decode(t),e.name);if(!n.data)throw Error(n.reason??`Not a recognized report`);let r=new Uint8Array(await crypto.subtle.digest(`SHA-256`,t)).toBase64({alphabet:`base64url`,omitPadding:!0});return{hash:r,key:B(r,typeof n.data.source==`string`?n.data.source:null)}}async function U(e,{source:t,deps:n,api:r,signal:i}){let a=JSON.parse(await n.hydrateKey(`deepview.workspaces`)||`[]`),o=(Array.isArray(a)?a:a.workspaces??[]).filter(e=>typeof e.id==`string`&&typeof e.name==`string`);i.throwIfAborted();let s=await t.list(e),c=V(e,(await r.send(`/api/admin/${z(e)}`))[z(e)]),l=o.map(e=>({id:e.id,name:e.name,items:[]})),u={id:null,name:`Not in a workspace`,items:[]},d=[];for(let r of s){i.throwIfAborted();let a={value:r.value,name:r.label,key:r.value,synced:!1,present:!1,error:``};if(e===`report`)try{Object.assign(a,await t.importItem(e,a.value,H,{signal:i})),a.syncHash=await n.reportSyncHash(a.value)}catch(e){i.throwIfAborted(),a.error=String(e?.message??e)}i.throwIfAborted(),a.present=c.has(a.key);let s=!1;o.forEach((t,r)=>{if(!t[z(e)]?.includes(a.value))return;let i=n.localContentSyncStatus(t.id,e,a.value,a.syncHash);a.synced||=i.synced,l[r].items.push({item:a,...i}),s=!0}),s||u.items.push({item:a,synced:!1,cached:!1}),d.push(a)}return{kind:e,items:d,groups:[...l,u].filter(e=>e.items.length>0)}}async function W(e,t,{source:n,api:r,signal:i,progress:a=()=>{},imported:o=new Set}){let{kind:s}=e,c=V(s,(await r.send(`/api/admin/${z(s)}`))[z(s)]),l=new Set(t),u=[],d=0;for(let t of e.items)if(i.throwIfAborted(),!(!l.has(t.value)||t.error||t.present)){if(c.has(t.key)){t.present=!0;continue}a(`Importing ${t.name}\u2026`),d++;try{await n.importItem(s,t.value,async e=>{let n=s===`report`?(await H(e)).key:await p(new Uint8Array(await e.arrayBuffer()));if(i.throwIfAborted(),n!==t.key)throw Error(`${t.name} changed. Choose files again before importing.`);if((await r.send(`/api/admin/${z(s)}`,e,{[`x-${s}-filename`]:encodeURIComponent(e.name)})).conflict)throw Error(`Could not import ${t.name}. Try again.`)},{signal:i})}catch(e){if(E(e,i))throw e;u.push(`${t.name}: ${T(e)}`);continue}c.add(t.key),t.present=!0,o.add(t.value)}if(u.length>0)throw Error(`Imported ${d-u.length} of ${d} ${s}s. Could not import ${u.join(`; `)}. Import again to retry them.`);return o.size}var G=(e,t)=>e===void 0?`managed-only`:t===void 0?`local-only`:`mismatch`;function K(e,t){let n=t.slice(),r=e.map(e=>{let t=n.indexOf(e);return t!==-1&&n.splice(t,1),{text:e,different:t===-1}}),i=e.slice(),a=t.map(e=>{let t=i.indexOf(e);return t!==-1&&i.splice(t,1),{text:e,different:t===-1}});return!r.some(e=>e.different)&&!a.some(e=>e.different)?null:{property:`comment`,local:r,managed:a,kind:r.some(e=>e.different)?a.some(e=>e.different)?`mismatch`:`local-only`:`managed-only`}}function q(e,t){let n=f(e)??{},r=f(t.entry)??{},i=[];for(let e of[`triage`,`color`,`fix`,`flagged`])n[e]!==r[e]&&i.push({property:e,local:n[e],managed:r[e],kind:G(n[e],r[e])});let a=K(n.comment?[n.comment]:[],t.comments.map(e=>e.body));return a&&i.push(a),n.ignoredReports?.length&&i.push({property:`ignoredReports`,local:[...new Set(n.ignoredReports)],managed:void 0,kind:`local-only`}),i}async function J(e,{lookup:t,triage:n,matched:r,findings:i,api:a,signal:o}){let s=[...new Set(e.findingIds)].filter(e=>t.has(e)&&!r.has(e));for(let c=0;c<s.length;c+=200){let l=s.slice(c,c+200);if(l.some(e=>e.length>100))throw Error(`A shared finding ID exceeds the managed triage limit.`);o.throwIfAborted();let{snapshots:u}=await a.send(`/api/admin/reports/${encodeURIComponent(e.id)}/import-triage`,{findingIds:l});o.throwIfAborted();for(let e of l){if(!u?.[e])throw Error(`The server did not return the requested triage snapshot.`);let a=q(n[e],u[e]);a.length>0&&i.push({id:e,finding:t.get(e),differences:a}),r.add(e)}}}async function Y({source:e,readTriage:t,api:n,signal:r,progress:i=()=>{}}){let a=new Map,c=[];for(let t of await e.list(`report`)){r.throwIfAborted(),i(`Reading ${t.label}\u2026`);try{let n=await e.importItem(`report`,t.value,async e=>{let t=await e.text(),n=o(t,e.name);if(!n.data)throw Error(n.reason??`Not a recognized report`);return n.format===`links`?[]:(await s(t,e.name))?.findings??[]},{signal:r});r.throwIfAborted();for(let e of n)typeof e.id!=`string`||!e.id||(a.has(e.id)||a.set(e.id,{...e,reports:[]}),a.get(e.id).reports.push(t.label))}catch(e){r.throwIfAborted(),c.push({name:t.label,reason:String(e?.message??e)})}}let l=await t()??{};if(r.throwIfAborted(),typeof l!=`object`||Array.isArray(l))throw Error(`Invalid local triage.`);let u=[],d=new Set;if(a.size===0)return{matched:0,localFindings:0,findings:u,skipped:c};let f;do{r.throwIfAborted(),i(`Comparing local and managed triage…`);let e=await n.send(`/api/admin/reports/finding-ids`+(f?`?after=${encodeURIComponent(f)}`:``));r.throwIfAborted();for(let t of e.reports)await J(t,{lookup:a,triage:l,matched:d,findings:u,api:n,signal:r});f=e.nextCursor}while(f);return r.throwIfAborted(),{matched:d.size,localFindings:a.size,findings:u,skipped:c}}function X(n,r){if(customElements.get(`managed-admin-import`))return;class i extends n{static styles=[h(t),h(v)];static properties={localDeps:{attribute:!1},_busy:{state:!0},_error:{state:!0},_message:{state:!0},_plan:{state:!0},_catalog:{state:!0},_localOpen:{state:!0},_workspaces:{state:!0},_localId:{state:!0},_triage:{state:!0},_repo:{state:!0},_drag:{state:!0}};constructor(){super(),this._busy=!1,this._error=``,this._message=``,this._plan=null,this._catalog=null,this._workspaces=[],this._localOpen=!1,this._localId=``,this._triage=``,this._repo=null,this._files=[],this._drag=!1,this._local=!1,this._over=e=>{e.dataTransfer?.types?.includes(`Files`)&&(e.preventDefault(),this._drag=!0)},this._drop=e=>{e.dataTransfer?.types?.includes(`Files`)&&(e.preventDefault(),e.stopPropagation(),this._drag=!1,this._busy||(this._files.push(...e.dataTransfer.files),this._nextFile()))},this._localChanged=()=>{this._workspaces=[],this._localId=``,!this._unlocking&&(this._local&&(this._plan=null),(this._local||this._importingTriage||this._importingContent||this._comparingTriage)&&(this._operation?.abort(),this._message=``,this._error=this._comparingTriage?`Local data changed or was locked. Compare triage again to continue.`:this._importingContent?`Local data changed or was locked. Choose files again to continue.`:this._importingTriage?`Local data changed or was locked. Import triage again to continue.`:`Local data changed or was locked. Choose the workspace again.`))},this._blur=()=>{this._readingLocal&&this._localChanged()}}connectedCallback(){super.connectedCallback(),this.addEventListener(`dragover`,this._over),this.addEventListener(`drop`,this._drop),globalThis.addEventListener(`blur`,this._blur),globalThis.addEventListener(`storage`,this._localChanged),this._offVault=this.localDeps?.onVaultStateChange(this._localChanged),this._loadCatalog()}disconnectedCallback(){this._operation?.abort(),this._offVault?.(),this._plan=null,this._files=[],this.removeEventListener(`dragover`,this._over),this.removeEventListener(`drop`,this._drop),globalThis.removeEventListener(`blur`,this._blur),globalThis.removeEventListener(`storage`,this._localChanged),super.disconnectedCallback()}updated(e){e.has(`session`)&&(this._role!==`admin`||e.get(`session`)?.id!==this.session?.id)&&(this._operation?.abort(),this._plan=null,this._files=[])}async _action(e){if(this._busy||this._role!==`admin`)return;let t=this._operation=new AbortController,n=AbortSignal.any([t.signal,this.appState.sessionController.signal]);this._busy=!0,this._error=``;try{await e(n),n.throwIfAborted()}catch(e){n.aborted||(this._error=String(e?.message??e))}finally{this._operation===t&&(this._busy=!1)}}async _loadCatalog(){if(this._role===`admin`)try{await this._loadCollection(`workspace-import:catalog`,`import options`,async e=>{let t=j(r,this.session,e),[n,i,a,o]=await Promise.all([t.send(`/api/admin/reports`),t.send(`/api/admin/teams`),t.send(`/api/admin/bundles`),t.send(`/api/admin/repositories/aliases`)]);return{repos:n.repos,teams:i.teams,bundles:a.bundles,aliases:o.aliases}},e=>{this._catalog=e})}catch(e){this._error=String(e?.message??e)}}_browse(){let e=document.createElement(`input`);e.type=`file`,e.multiple=!0,e.accept=`.enc,.gz,.json`,e.addEventListener(`change`,()=>{this._files.push(...e.files),this._nextFile()},{once:!0}),e.click()}async _prepare(e,t){if(!e)return;if(this._catalog||await this._loadCatalog(),t.throwIfAborted(),!this._catalog)throw Error(`Could not load repositories. Try again.`);let n=await A(e,this._catalog.repos,this._catalog.aliases);t.throwIfAborted();let r=new Set(this._catalog.teams.map(e=>e.name)),i=n.name||`Imported workspace`,a=2;for(;r.has(n.name);){let e=` (${a++})`;n.name=i.slice(0,100-e.length)+e}let o=new Set(n.reports.map(e=>e.repoId).filter(e=>e!=null));this._repo=o.size===1?[...o][0]:null,this._triage=Object.keys(n.triage).length>0?``:`skip`,this._plan=n,this._message=``}async _nextFile(){if(this._files.length===0||this._busy)return;let e=this._files.shift();this._local=!1,this._plan=null,await this._action(async t=>{let n=await O(e,this.promptPassword);t.throwIfAborted(),await this._prepare(n,t)})}async _unlock(e,t){this._unlocking=!0;try{return!e.locked||await e.unlock({signal:t})}finally{this._unlocking=!1}}async _chooseLocal(){this._localOpen=!0,await this._action(async e=>{let t=R(this.localDeps);await this._unlock(t,e)&&(e.throwIfAborted(),this._workspaces=await t.list({signal:e}))})}async _readLocal(){if(!this._localId)return;let e=this._localId;this._local=!0,this._plan=null,await this._action(async t=>{let n=R(this.localDeps);if(await this._unlock(n,t)){this._readingLocal=!0;try{await this._prepare(await n.read(e,{signal:t}),t)}finally{this._readingLocal=!1}}})}async _import(){!this._plan||!this._triage||!this._csrf||(await this._action(async e=>{if(this._local&&R(this.localDeps).locked)throw Error(`Unlock local data and choose the workspace again.`);let t=this._plan,n=[`teams`,`reports`,`bundles`,`history`,`workspace-import`,`scan-sources`,`repo-impact`];try{let i=await this.appState.mutate(()=>I(t,{api:j(r,this.session,e),session:this.session,defaultRepo:this._repo,includeTriage:this._triage===`include`,resolveConflicts:this.resolveConflicts,signal:e,progress:e=>{this._message=e}}),n);this._catalog.teams.push(i),this._message=`Imported into ${i.name}.`,this._plan=null}finally{this.appState.invalidate(n),t.team&&this.dispatchEvent(new CustomEvent(`managed-import-complete`,{bubbles:!0,composed:!0}))}}),!this._plan&&!this._error&&await this._nextFile())}async _importLocalTriage(){this._csrf&&await this._action(async e=>{this._importingTriage=!0,this._message=``;let t=new Set,n=[`reports`,`history`];try{let n=L(this.localDeps);if(!await this._unlock(n,e))return;this._readingLocal=!0;let i;try{i=await n.read({signal:e})}finally{this._readingLocal=!1}let a=await y(i,{api:j(r,this.session,e),session:this.session,resolveConflicts:this.resolveConflicts,signal:e,importedIds:t,confirmImport:async t=>(await this.confirmTriageImport({...t,signal:e}))?.confirmed===!0});if(e.throwIfAborted(),a===null)return;this._message=a?`Imported triage for ${a} finding${a===1?``:`s`}.`:`No local triage matches findings in managed reports.`}finally{this._importingTriage=!1,this.appState.invalidate(n),t.size>0&&this.dispatchEvent(new CustomEvent(`managed-import-complete`,{bubbles:!0,composed:!0}))}})}async _compareLocalTriage(){this._csrf&&await this._action(async e=>{this._comparingTriage=!0,this._message=``;let t=this.localImportSource,n=t.subscribe(this._localChanged);try{if(!await this._unlock(t,e))return;e.throwIfAborted(),this._readingLocal=!0;let n=L(this.localDeps),i=await Y({source:t,signal:e,readTriage:()=>n.read({signal:e}),api:j(r,this.session,e),progress:e=>{this._message=e}});e.throwIfAborted(),this._message=``,await this.showTriageComparison({comparison:i,signal:e})}finally{n(),this._readingLocal=!1,this._comparingTriage=!1,this._message=``}})}async _importLocalContent(e){this._csrf&&await this._action(async t=>{this._importingContent=!0,this._message=``;let n=this.localImportSource,i=[`reports`,`bundles`,`bundle-metadata`,`history`,`workspace-import`,`scan-sources`,`repo-impact`],a=new Set,o=n.subscribe(this._localChanged);try{if(!await this._unlock(n,t))return;t.throwIfAborted(),this._readingLocal=!0;let i=j(r,this.session,t),o=await U(e,{source:n,deps:this.localDeps,api:i,signal:t}),s=await this.confirmContentImport({plan:o,signal:t});if(t.throwIfAborted(),!s?.confirmed)return;let c=await W(o,s.selected,{source:n,api:i,signal:t,imported:a,progress:e=>{this._message=e}});this._message=`Imported ${c} ${e}${c===1?``:`s`}.`}finally{o(),this._readingLocal=!1,this._importingContent=!1,this.appState.invalidate(i),a.size>0&&this.dispatchEvent(new CustomEvent(`managed-import-complete`,{bubbles:!0,composed:!0}))}})}render(){if(this._role!==`admin`)return _;let t=this._plan,n=t?Object.keys(t.triage).length:0,r=new Set([...t?.references??[],...t?.bundles.map(e=>e.integrity)??[]]),i=(this._catalog?.bundles??[]).filter(e=>r.has(e.integrity)),a=t?.references.filter(e=>!t.bundles.some(t=>t.integrity===e)).length??0;return g`<div class="wrap" @dragleave="${()=>{this._drag=!1}}">${e(`manage-import`,this._role,this.allowShare)}<h1>Import</h1><section class="triage-import" aria-label="Import local files"><div class="actions"><button type="button" class="btn" ?disabled="${this._busy||!this._csrf}" @click="${()=>this._importLocalContent(`bundle`)}">Import bundles</button> <button type="button" class="btn" ?disabled="${this._busy||!this._csrf}" @click="${()=>this._importLocalContent(`report`)}">Import reports</button></div><p>Choose files from this browser, grouped by workspace. Import files without teams or triage.</p></section><section class="triage-import" aria-label="Local triage"><div class="actions"><button type="button" class="btn" ?disabled="${this._busy||!this._csrf}" @click="${()=>this._importLocalTriage()}">Import triage</button> <button type="button" class="btn" ?disabled="${this._busy||!this._csrf}" @click="${()=>this._compareLocalTriage()}">Compare triage</button></div><p>Import saved triage and comments for findings already in managed reports.<br>Unmatched data stays in this browser.<br>Conflicting values prompt for resolution; per-report ignores are skipped.</p></section><h2>Import workspace</h2><p class="intro ui-hint">Create a new team from a workspace export or a workspace stored in this browser.</p><section class="${`workspace-drop ${this._drag?`dragging`:``}`}" aria-label="Workspace files"><strong>Drop workspace files here</strong><span>Encrypted exports, JSON, or compressed JSON. Encrypted files prompt for a password.</span><div class="actions"><button type="button" class="btn" ?disabled="${this._busy||!this._catalog}" @click="${()=>this._browse()}">Choose files</button> <button type="button" class="btn" ?disabled="${this._busy}" @click="${()=>this._chooseLocal()}">Choose local workspace</button></div></section>${this._localOpen?g`<section class="local-choice"><label for="local-workspace">Local workspace</label> <select id="local-workspace" .value="${this._localId}" ?disabled="${this._busy}" @change="${e=>{this._localId=e.target.value}}"><option value="">Choose a workspace…</option>${this._workspaces.map(e=>g`<option value="${e.id}">${e.name}</option>`)}</select> <button type="button" class="btn" ?disabled="${this._busy||!this._localId}" @click="${()=>this._readLocal()}">Select workspace</button> ${!this._busy&&this._workspaces.length===0?g`<p class="ui-hint">No unlocked local workspaces. Choose local workspace to unlock or refresh.</p>`:_}</section>`:_} ${t?g`<section class="import-preview" aria-label="Import options">${t.team?g`<p>Team ${t.team.name} has been created. Retry continues its remaining import steps.</p>`:_} <label for="import-team">New team name</label><input id="import-team" maxlength="100" .value="${t.name}" ?disabled="${this._busy||!!t.team}" @input="${e=>{t.name=e.target.value,this.requestUpdate()}}"><p>${t.reports.length} reports / links · ${r.size} source bundles · ${n} triaged findings</p><label for="import-repo">Repository for files and source bundles without an active repository</label> <select id="import-repo" .value="${String(this._repo??``)}" ?disabled="${this._busy||!!t.team}" @change="${e=>{this._repo=e.target.value?Number(e.target.value):null}}"><option value="" ?selected="${this._repo==null}">Choose a repository…</option>${(this._catalog?.repos??[]).map(e=>g`<option value="${String(e.repoId)}" ?selected="${this._repo===e.repoId}">${e.fullName}</option>`)}</select><p>Declared report repositories and directories are preserved. Stored reports without an active repository use the selected repository. The new team receives those repository paths; other published reports in the same paths are also visible to that team.</p><ul>${t.reports.map(e=>g`<li>${e.name}<span>${e.links?`Global deduplication — enabled for all teams`:e.github??`Uses selected repository`}${e.links||e.github==null||e.repoId!=null?``:e.embedded?` — connect this repository first`:` — not connected; uses selected repository`}</span></li>`)}</ul>${i.length>0?g`<p>Existing source bundles in active repositories keep their locations. The new team also receives access to those directories. Unassigned bundles and bundles in inactive repositories use the selected repository.</p><ul>${i.map(e=>g`<li>${e.filename}<span>${e.repoFullName?`${e.repoFullName}${e.repoDirectory?`/${e.repoDirectory}`:``}`:`Uses selected repository`}</span></li>`)}</ul>`:_} ${a?g`<p>${a} referenced source bundles have no bytes in this export. Reports can use matching bundles already on the server.</p>`:_} ${n?g`<fieldset ?disabled="${this._busy||!!t.team}"><legend>Import triage?</legend><label><input type="radio" name="import-triage" value="include" ?checked="${this._triage===`include`}" @change="${()=>{this._triage=`include`}}"> Include triage and comments</label> <label><input type="radio" name="import-triage" value="skip" ?checked="${this._triage===`skip`}" @change="${()=>{this._triage=`skip`}}"> Skip triage</label><p>Conflicting values prompt for resolution. Triage stays shared by finding ID across teams. Per-report local ignores are not imported.</p></fieldset>`:_} <button type="button" class="btn primary" ?disabled="${this._busy||!this._triage||!this._csrf}" @click="${()=>this._import()}">${this._busy?`Importing…`:t.team?`Retry remaining import`:`Import workspace`}</button></section>`:_} ${this._message?g`<p role="status">${this._message}</p>`:_} ${this._error?g`<p class="error" role="alert">${this._error}${this._catalog?_:g`<button class="btn" @click="${()=>this._loadCatalog()}">Retry</button>`}</p>`:_} ${this._files.length>0&&!this._busy?g`<button class="btn" @click="${()=>this._nextFile()}">Next workspace file (${this._files.length} waiting)</button>`:_}</div>`}}customElements.define(`managed-admin-import`,i)}export{X as registerWorkspaceImport};
|