diff --git a/architecture/webapp-server.md b/architecture/webapp-server.md index 87ec4f9..005fe8e 100644 --- a/architecture/webapp-server.md +++ b/architecture/webapp-server.md @@ -371,7 +371,7 @@ classDiagram class ShareOpen { +Count +Last } - note for ShareOpen "The receipt on a public link: share-kind buckets only, which is what makes Last mean last OPENED — HeatEntry.LastRead is cross-kind, so a member viewing the file in the hub would otherwise move the date. Counts, never openers: the share actor is token+IP. Keyed by path, so two tokens on one file report the same number. Callers build the map ONCE per project and index it; a per-share call is a full byKey scan per row" + note for ShareOpen "The receipt on a public link: share-kind buckets only, which is what makes Last mean last OPENED — HeatEntry.LastRead is cross-kind, so a member viewing the file in the hub would otherwise move the date. Counts, never openers: the share actor is token+IP+UA hash (token+IP alone folded a whole office into one reader, BEA-151 — the browser component is a heuristic that raises the floor, never identity, and is hashed because Record persists the actor). Keyed by path, so two tokens on one file report the same number. Callers build the map ONCE per project and index it; a per-share call is a full byKey scan per row" class QuotaProvider { <> diff --git a/internal/webapp/frontend/src/components/SharesTable.tsx b/internal/webapp/frontend/src/components/SharesTable.tsx index 34a4d3b..6edb012 100644 --- a/internal/webapp/frontend/src/components/SharesTable.tsx +++ b/internal/webapp/frontend/src/components/SharesTable.tsx @@ -51,13 +51,16 @@ export function shareDetail(s: ShareInfo, showProject: boolean): string { return bits.join(" · "); } -// The two honesties about the number, worded once per section rather than -// once per row: opens are debounced VISITS (readDebounce, reads.go), and the -// count is per FILE not per link (heat is keyed by path), so two tokens on -// one file report the same number. +// The honesties about the number, worded once per section rather than once +// per row: opens are debounced VISITS (readDebounce, reads.go) keyed by +// browser+network rather than by person (shareActor, shares.go) — so the note +// states the residual instead of promising precision the signal lacks — and +// the count is per FILE not per link (heat is keyed by path), so two tokens +// on one file report the same number. export const OPENS_NOTE = "Opens count how many times a file has been read through a public link. " + - "Repeat opens by the same reader within 10 minutes count once."; + "Repeat opens from the same browser and network within 10 minutes count once — " + + "two people on one network using the same browser still count as one."; export function SharesTable({ shares, diff --git a/internal/webapp/reads.go b/internal/webapp/reads.go index 934abcd..39399e8 100644 --- a/internal/webapp/reads.go +++ b/internal/webapp/reads.go @@ -460,9 +460,9 @@ type ShareOpen struct { // HeatEntry.LastRead is cross-kind, so a member viewing the file in the hub // would otherwise move the "opened through the link" date. // -// Counts, never identities — the share actor is token+"/"+IP, a public -// credential joined to an IP, and it must not leave the ledger. There is -// deliberately no distinct-openers field. +// Counts, never identities — the share actor is token+"/"+IP+"/"+UA hash, a +// public credential joined to a network and a browser, and it must not leave +// the ledger. There is deliberately no distinct-openers field. // // One byKey scan per project, never one per share: callers build this map // once and index it, because byKey is the full map and a project with 40 diff --git a/internal/webapp/sec_ledger_test.go b/internal/webapp/sec_ledger_test.go index cec6d66..e2fdcab 100644 --- a/internal/webapp/sec_ledger_test.go +++ b/internal/webapp/sec_ledger_test.go @@ -357,8 +357,12 @@ func TestSec_Share_PublicHitRecordsShareKindEndToEnd(t *testing.T) { if b.Project != p.ID || b.Path != "hr/eng/payroll.md" { t.Errorf("share visit recorded (%s, %s), want (%s, hr/eng/payroll.md)", b.Project, b.Path, p.ID) } - if want := token + "/203.0.113.7"; b.Actor != want { - t.Errorf("share actor = %q, want %q", b.Actor, want) + // token/ip/uahash (BEA-151): the browser component is what stops a whole + // office behind one NAT from reading as one person. Asserted as a PREFIX + // so the identity half — link plus network, never a name — stays pinned + // without pinning the hash of an empty User-Agent. + if want := token + "/203.0.113.7/"; !strings.HasPrefix(b.Actor, want) { + t.Errorf("share actor = %q, want prefix %q", b.Actor, want) } // The member view: a share hit is share traffic, never a human reader. @@ -450,6 +454,14 @@ func TestSec_Ledger_ReplicationAndHistoryViewsAreNeverReads(t *testing.T) { // visitor controls — the query string, the method, the headers, the // casing of the token, X-Forwarded-For? // - can a visitor get an identity of its choosing recorded as an actor? +// +// User-Agent is the ONE exception, and it is deliberate (BEA-151): the actor +// key includes a hash of it, because without it three people in one office +// were one reader and the share panel reported "1 open" for all of them. So a +// visitor CAN split its own visits by rotating UAs — bounded by the per-IP +// limiter above the handler (ratelimit.go) and by retention folding, and it +// inflates only the count on a link the visitor already holds. Asserted below +// as intended behavior rather than left to look like a hole. func TestSec_Share_VisitorCannotInflateOrRedirectTheLedger(t *testing.T) { h, srv, c, p := permHub(t) secledReads(t, srv) @@ -472,8 +484,6 @@ func TestSec_Share_VisitorCannotInflateOrRedirectTheLedger(t *testing.T) { {"/s/" + token + "?cachebust=2", nil}, {"/s/" + token + "?", nil}, {"/s/" + token + "?download=1&x=" + strings.Repeat("y", 200), nil}, - {"/s/" + token, map[string]string{"User-Agent": "one"}}, - {"/s/" + token, map[string]string{"User-Agent": "two"}}, {"/s/" + token, map[string]string{"X-Forwarded-For": "10.1.1.1"}}, {"/s/" + token, map[string]string{"X-Forwarded-For": "10.1.1.2, 10.1.1.3"}}, {"/s/" + token, map[string]string{"X-Real-IP": "10.2.2.2"}}, @@ -504,6 +514,18 @@ func TestSec_Share_VisitorCannotInflateOrRedirectTheLedger(t *testing.T) { t.Errorf("one visitor at one address produced %d ledger buckets — the 10-minute "+ "visit debounce is defeated by something the visitor chooses: %+v", len(got), got) } + + // The documented exception: distinct browsers are distinct readers, so two + // UAs are two buckets. That is the fix, not a defeat of the debounce — and + // the actor still says only "this link, this network, some browser". + for _, ua := range []string{"one", "two"} { + secledGet(h, "/s/"+token, addr, map[string]string{"User-Agent": ua}) + } + got = secledBuckets(srv.Reads) + if len(got) != 3 { + t.Errorf("two more browsers on one network produced %d buckets in total, want 3 — "+ + "distinct browsers must count separately (BEA-151): %+v", len(got), got) + } for _, b := range got { if b.Project != p.ID { t.Errorf("a share visitor wrote a bucket for project %s, but the share is on %s: %+v", @@ -512,8 +534,8 @@ func TestSec_Share_VisitorCannotInflateOrRedirectTheLedger(t *testing.T) { if b.Kind != ReadKindShare { t.Errorf("an anonymous share visitor recorded a %s-kind bucket: %+v", b.Kind, b) } - if !strings.HasPrefix(b.Actor, token+"/") { - t.Errorf("share actor %q is not token/ip — the visitor chose part of it: %+v", b.Actor, b) + if !strings.HasPrefix(b.Actor, token+"/203.0.113.7/") { + t.Errorf("share actor %q is not token/ip/browser — the visitor chose the identifying part of it: %+v", b.Actor, b) } for _, planted := range []string{"alice@x.io", "dev-alice", "pwned", "10.1.1.1", "10.1.1.2", "10.2.2.2"} { if strings.Contains(b.Actor, planted) { diff --git a/internal/webapp/shares.go b/internal/webapp/shares.go index 7a2bf27..dc69700 100644 --- a/internal/webapp/shares.go +++ b/internal/webapp/shares.go @@ -1,6 +1,8 @@ package webapp import ( + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" "html" @@ -500,6 +502,21 @@ func (s *Server) shareCreatorStillBelongs(sh Share) bool { // handleShared serves a share link: public, sandboxed, always the latest // synced content. +// shareActor identifies one reader of a link well enough to debounce their +// own reloads without folding a whole office into a single visit: token+IP +// alone made every browser behind one NAT the same reader (BEA-151). +// +// The User-Agent is HASHED, never stored raw — Record persists the actor into +// the read buckets and out through ReadRepo, and a raw User-Agent there is a +// fingerprint sitting in storage indefinitely. Truncated because this only +// ever needs to GROUP, never to identify, and it must not leave the ledger +// either way. token+"/"+IP stays the prefix so the existing leak assertions +// keep covering the wider key. +func (s *Server) shareActor(r *http.Request, token string) string { + sum := sha256.Sum256([]byte(r.UserAgent())) + return token + "/" + s.clientIP(r) + "/" + hex.EncodeToString(sum[:8]) +} + func (s *Server) handleShared(w http.ResponseWriter, r *http.Request) { // Sandbox everything under /s/ before anything can answer the request: // shared content executes in an opaque origin (scripts allowed — charts in @@ -543,9 +560,9 @@ func (s *Server) handleShared(w http.ResponseWriter, r *http.Request) { return } fi := snap.files[sp] - // A share hit is external consumption. Actor is token+IP: one audience - // member reloading is debounced to a visit, distinct visitors still count. - s.Reads.Record(sh.Project, sp, ReadKindShare, sh.Token+"/"+s.clientIP(r)) + // A share hit is external consumption: one audience member reloading is + // debounced to a visit, distinct visitors still count. + s.Reads.Record(sh.Project, sp, ReadKindShare, s.shareActor(r, sh.Token)) // Share links are the only unauthenticated door to stored bytes, so they // are the only egress a plan actually caps. The per-IP limiter above diff --git a/internal/webapp/shares_test.go b/internal/webapp/shares_test.go index 47c7ad6..4d216d8 100644 --- a/internal/webapp/shares_test.go +++ b/internal/webapp/shares_test.go @@ -583,12 +583,85 @@ func TestShareOpensOnTheWire(t *testing.T) { t.Fatal("an opened link must carry last_opened") } - // The actor is token+"/"+IP — a public credential joined to an IP. It - // must not appear anywhere in the response, in any shape. + // opens reads one link's count and last_opened back off the WIRE rather + // than out of the ledger, because the wire is what the panel shows. + opens := func(tok string) (float64, time.Time) { + t.Helper() + for _, sh := range listShares(t, srv, h, p.ID) { + if sh["token"] != tok { + continue + } + last, _ := sh["last_opened"].(string) + if last == "" { + return sh["opens"].(float64), time.Time{} + } + ts, err := time.Parse(time.RFC3339, last) + if err != nil { + t.Fatalf("last_opened %q: %v", last, err) + } + return sh["opens"].(float64), ts + } + t.Fatalf("link %s missing from the list", tok) + return 0, time.Time{} + } + // The debounce collapses reloads; it does not cap a link. Only the clock + // is under test, so it is moved rather than waited on. + ageDebounce := func() { + srv.Reads.mu.Lock() + defer srv.Reads.mu.Unlock() + for k, v := range srv.Reads.seen { + srv.Reads.seen[k] = v.Add(-readDebounce - time.Minute) + } + } + ageDebounce() + if rec := do(t, h, "GET", "/s/"+token, nil); rec.Code != 200 { + t.Fatalf("public fetch past the window: %d %s", rec.Code, rec.Body) + } + if got, _ := opens(token); got != 2 { + t.Fatalf("opens = %v after a reload past the debounce window, want 2", got) + } + + // Three readers, ONE network, seconds apart: distinct browsers are + // distinct actors, so the count moves and last_opened follows the newest + // hit. token+"/"+IP alone made a whole office one reader (BEA-151) — + // httptest hands every request the same 192.0.2.1, which is exactly the + // NAT the personas were sitting behind. + uas := []string{ + "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_5) Safari/605.1", + "Mozilla/5.0 (X11; Linux x86_64) Firefox/128.0", + "Mozilla/5.0 (Windows NT 10.0; Win64) Chrome/126.0.0.0", + } + var afterFirst time.Time + for i, ua := range uas { + req := jsonReq(t, "GET", "/s/"+unopened, nil) + req.Header.Set("User-Agent", ua) + if rec := doHTTP(h, req); rec.Code != 200 { + t.Fatalf("reader %d: %d %s", i, rec.Code, rec.Body) + } + if i == 0 { + _, afterFirst = opens(unopened) + } + } + got, afterThird := opens(unopened) + if got != 3 { + t.Fatalf("three readers on one network reported %v opens, want 3 — distinct browsers are distinct readers", got) + } + if !afterThird.After(afterFirst) { + t.Fatalf("last_opened stuck at %s after two later readers; it must follow the newest open", afterFirst) + } + + // The actor is token+"/"+IP+"/"+UA hash — a public credential joined to a + // network and a browser. No part of it may appear anywhere in the + // response, in any shape; a hash is not an exemption. req := jsonReq(t, "GET", "/api/p/"+p.ID+"/shares", nil) authAs(t, srv, req) body := doHTTP(h, req).Body.String() - for _, leak := range []string{token + "/", "192.0.2.1", "actor", "openers"} { + leaks := []string{token + "/", unopened + "/", "192.0.2.1", "actor", "openers"} + for _, ua := range append(uas, "") { + sum := sha256.Sum256([]byte(ua)) + leaks = append(leaks, hex.EncodeToString(sum[:8])) + } + for _, leak := range leaks { if strings.Contains(body, leak) { t.Fatalf("shares response leaks %q: %s", leak, body) } diff --git a/internal/webapp/static/assets/index-C17b7d2I.js b/internal/webapp/static/assets/index-DvCVMCS-.js similarity index 95% rename from internal/webapp/static/assets/index-C17b7d2I.js rename to internal/webapp/static/assets/index-DvCVMCS-.js index b49281c..8918a33 100644 --- a/internal/webapp/static/assets/index-C17b7d2I.js +++ b/internal/webapp/static/assets/index-DvCVMCS-.js @@ -112,7 +112,7 @@ Error generating stack: `+c.message+` `)}x.write("payload.value = newResult;"),x.write("return payload;");const T=x.compile();return(O,N)=>T(b,O,N)};let l;const u=Ru,d=!cg.jitless,p=d&&e5.value,y=t.catchall;let v;e._zod.parse=(b,x)=>{v??(v=a.value);const w=b.value;return u(w)?d&&p&&x?.async===!1&&x.jitless!==!0?(l||(l=o(t.shape)),b=l(b,x),y?bC([],w,b,x,v,e):b):r(b,x):(b.issues.push({expected:"object",code:"invalid_type",input:w,inst:e}),b)}});function Vx(e,t,r,a){for(const l of e)if(l.issues.length===0)return t.value=l.value,t;const o=e.filter(l=>!$s(l));return o.length===1?(t.value=o[0].value,o[0]):(t.issues.push({code:"invalid_union",input:t.value,inst:r,errors:e.map(l=>l.issues.map(u=>Ma(u,a,Aa())))}),t)}const P6=me("$ZodUnion",(e,t)=>{Vt.init(e,t),pt(e._zod,"optin",()=>t.options.some(a=>a._zod.optin==="optional")?"optional":void 0),pt(e._zod,"optout",()=>t.options.some(a=>a._zod.optout==="optional")?"optional":void 0),pt(e._zod,"values",()=>{if(t.options.every(a=>a._zod.values))return new Set(t.options.flatMap(a=>Array.from(a._zod.values)))}),pt(e._zod,"pattern",()=>{if(t.options.every(a=>a._zod.pattern)){const a=t.options.map(o=>o._zod.pattern);return new RegExp(`^(${a.map(o=>fg(o.source)).join("|")})$`)}});const r=t.options.length===1?t.options[0]._zod.run:null;e._zod.parse=(a,o)=>{if(r)return r(a,o);let l=!1;const u=[];for(const d of t.options){const m=d._zod.run({value:a.value,issues:[]},o);if(m instanceof Promise)u.push(m),l=!0;else{if(m.issues.length===0)return m;u.push(m)}}return l?Promise.all(u).then(d=>Vx(d,a,e,o)):Vx(u,a,e,o)}}),F6=me("$ZodIntersection",(e,t)=>{Vt.init(e,t),e._zod.parse=(r,a)=>{const o=r.value,l=t.left._zod.run({value:o,issues:[]},a),u=t.right._zod.run({value:o,issues:[]},a);return l instanceof Promise||u instanceof Promise?Promise.all([l,u]).then(([m,p])=>Ux(r,m,p)):Ux(r,l,u)}});function Qm(e,t){if(e===t)return{valid:!0,data:e};if(e instanceof Date&&t instanceof Date&&+e==+t)return{valid:!0,data:e};if(pl(e)&&pl(t)){const r=Object.keys(t),a=Object.keys(e).filter(l=>r.indexOf(l)!==-1),o={...e,...t};for(const l of a){const u=Qm(e[l],t[l]);if(!u.valid)return{valid:!1,mergeErrorPath:[l,...u.mergeErrorPath]};o[l]=u.data}return{valid:!0,data:o}}if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return{valid:!1,mergeErrorPath:[]};const r=[];for(let a=0;ad.l&&d.r).map(([d])=>d);if(l.length&&o&&e.issues.push({...o,keys:l}),$s(e))return e;const u=Qm(t.value,r.value);if(!u.valid)throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(u.mergeErrorPath)}`);return e.value=u.data,e}const V6=me("$ZodEnum",(e,t)=>{Vt.init(e,t);const r=cC(t.entries),a=new Set(r);e._zod.values=a,e._zod.pattern=new RegExp(`^(${r.filter(o=>t5.has(typeof o)).map(o=>typeof o=="string"?ad(o):o.toString()).join("|")})$`),e._zod.parse=(o,l)=>{const u=o.value;return a.has(u)||o.issues.push({code:"invalid_value",values:r,input:u,inst:e}),o}}),U6=me("$ZodTransform",(e,t)=>{Vt.init(e,t),e._zod.optin="optional",e._zod.parse=(r,a)=>{if(a.direction==="backward")throw new lC(e.constructor.name);const o=t.transform(r.value,r);if(a.async)return(o instanceof Promise?o:Promise.resolve(o)).then(u=>(r.value=u,r.fallback=!0,r));if(o instanceof Promise)throw new Bs;return r.value=o,r.fallback=!0,r}});function Hx(e,t){return t===void 0&&(e.issues.length||e.fallback)?{issues:[],value:void 0}:e}const xC=me("$ZodOptional",(e,t)=>{Vt.init(e,t),e._zod.optin="optional",e._zod.optout="optional",pt(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,void 0]):void 0),pt(e._zod,"pattern",()=>{const r=t.innerType._zod.pattern;return r?new RegExp(`^(${fg(r.source)})?$`):void 0}),e._zod.parse=(r,a)=>{if(t.innerType._zod.optin==="optional"){const o=r.value,l=t.innerType._zod.run(r,a);return l instanceof Promise?l.then(u=>Hx(u,o)):Hx(l,o)}return r.value===void 0?r:t.innerType._zod.run(r,a)}}),H6=me("$ZodExactOptional",(e,t)=>{xC.init(e,t),pt(e._zod,"values",()=>t.innerType._zod.values),pt(e._zod,"pattern",()=>t.innerType._zod.pattern),e._zod.parse=(r,a)=>t.innerType._zod.run(r,a)}),B6=me("$ZodNullable",(e,t)=>{Vt.init(e,t),pt(e._zod,"optin",()=>t.innerType._zod.optin),pt(e._zod,"optout",()=>t.innerType._zod.optout),pt(e._zod,"pattern",()=>{const r=t.innerType._zod.pattern;return r?new RegExp(`^(${fg(r.source)}|null)$`):void 0}),pt(e._zod,"values",()=>t.innerType._zod.values?new Set([...t.innerType._zod.values,null]):void 0),e._zod.parse=(r,a)=>r.value===null?r:t.innerType._zod.run(r,a)}),q6=me("$ZodDefault",(e,t)=>{Vt.init(e,t),e._zod.optin="optional",pt(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(r,a)=>{if(a.direction==="backward")return t.innerType._zod.run(r,a);if(r.value===void 0)return r.value=t.defaultValue,r;const o=t.innerType._zod.run(r,a);return o instanceof Promise?o.then(l=>Bx(l,t)):Bx(o,t)}});function Bx(e,t){return e.value===void 0&&(e.value=t.defaultValue),e}const G6=me("$ZodPrefault",(e,t)=>{Vt.init(e,t),e._zod.optin="optional",pt(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(r,a)=>(a.direction==="backward"||r.value===void 0&&(r.value=t.defaultValue),t.innerType._zod.run(r,a))}),Z6=me("$ZodNonOptional",(e,t)=>{Vt.init(e,t),pt(e._zod,"values",()=>{const r=t.innerType._zod.values;return r?new Set([...r].filter(a=>a!==void 0)):void 0}),e._zod.parse=(r,a)=>{const o=t.innerType._zod.run(r,a);return o instanceof Promise?o.then(l=>qx(l,e)):qx(o,e)}});function qx(e,t){return!e.issues.length&&e.value===void 0&&e.issues.push({code:"invalid_type",expected:"nonoptional",input:e.value,inst:t}),e}const K6=me("$ZodCatch",(e,t)=>{Vt.init(e,t),e._zod.optin="optional",pt(e._zod,"optout",()=>t.innerType._zod.optout),pt(e._zod,"values",()=>t.innerType._zod.values),e._zod.parse=(r,a)=>{if(a.direction==="backward")return t.innerType._zod.run(r,a);const o=t.innerType._zod.run(r,a);return o instanceof Promise?o.then(l=>(r.value=l.value,l.issues.length&&(r.value=t.catchValue({...r,error:{issues:l.issues.map(u=>Ma(u,a,Aa()))},input:r.value}),r.issues=[],r.fallback=!0),r)):(r.value=o.value,o.issues.length&&(r.value=t.catchValue({...r,error:{issues:o.issues.map(l=>Ma(l,a,Aa()))},input:r.value}),r.issues=[],r.fallback=!0),r)}}),Y6=me("$ZodPipe",(e,t)=>{Vt.init(e,t),pt(e._zod,"values",()=>t.in._zod.values),pt(e._zod,"optin",()=>t.in._zod.optin),pt(e._zod,"optout",()=>t.out._zod.optout),pt(e._zod,"propValues",()=>t.in._zod.propValues),e._zod.parse=(r,a)=>{if(a.direction==="backward"){const l=t.out._zod.run(r,a);return l instanceof Promise?l.then(u=>iu(u,t.in,a)):iu(l,t.in,a)}const o=t.in._zod.run(r,a);return o instanceof Promise?o.then(l=>iu(l,t.out,a)):iu(o,t.out,a)}});function iu(e,t,r){return e.issues.length?(e.aborted=!0,e):t._zod.run({value:e.value,issues:e.issues,fallback:e.fallback},r)}const Q6=me("$ZodReadonly",(e,t)=>{Vt.init(e,t),pt(e._zod,"propValues",()=>t.innerType._zod.propValues),pt(e._zod,"values",()=>t.innerType._zod.values),pt(e._zod,"optin",()=>t.innerType?._zod?.optin),pt(e._zod,"optout",()=>t.innerType?._zod?.optout),e._zod.parse=(r,a)=>{if(a.direction==="backward")return t.innerType._zod.run(r,a);const o=t.innerType._zod.run(r,a);return o instanceof Promise?o.then(Gx):Gx(o)}});function Gx(e){return e.value=Object.freeze(e.value),e}const X6=me("$ZodCustom",(e,t)=>{Nr.init(e,t),Vt.init(e,t),e._zod.parse=(r,a)=>r,e._zod.check=r=>{const a=r.value,o=t.fn(a);if(o instanceof Promise)return o.then(l=>Zx(l,r,a,e));Zx(o,r,a,e)}});function Zx(e,t,r,a){if(!e){const o={code:"custom",input:r,inst:a,path:[...a._zod.def.path??[]],continue:!a._zod.def.abort};a._zod.def.params&&(o.params=a._zod.def.params),t.issues.push(gl(o))}}var Kx;class J6{constructor(){this._map=new WeakMap,this._idmap=new Map}add(t,...r){const a=r[0];return this._map.set(t,a),a&&typeof a=="object"&&"id"in a&&this._idmap.set(a.id,t),this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(t){const r=this._map.get(t);return r&&typeof r=="object"&&"id"in r&&this._idmap.delete(r.id),this._map.delete(t),this}get(t){const r=t._zod.parent;if(r){const a={...this.get(r)??{}};delete a.id;const o={...a,...this._map.get(t)};return Object.keys(o).length?o:void 0}return this._map.get(t)}has(t){return this._map.has(t)}}function W6(){return new J6}(Kx=globalThis).__zod_globalRegistry??(Kx.__zod_globalRegistry=W6());const tl=globalThis.__zod_globalRegistry;function eL(e,t){return new e({type:"string",...Ie(t)})}function tL(e,t){return new e({type:"string",format:"email",check:"string_format",abort:!1,...Ie(t)})}function Yx(e,t){return new e({type:"string",format:"guid",check:"string_format",abort:!1,...Ie(t)})}function nL(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,...Ie(t)})}function rL(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v4",...Ie(t)})}function iL(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v6",...Ie(t)})}function aL(e,t){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v7",...Ie(t)})}function sL(e,t){return new e({type:"string",format:"url",check:"string_format",abort:!1,...Ie(t)})}function oL(e,t){return new e({type:"string",format:"emoji",check:"string_format",abort:!1,...Ie(t)})}function lL(e,t){return new e({type:"string",format:"nanoid",check:"string_format",abort:!1,...Ie(t)})}function cL(e,t){return new e({type:"string",format:"cuid",check:"string_format",abort:!1,...Ie(t)})}function uL(e,t){return new e({type:"string",format:"cuid2",check:"string_format",abort:!1,...Ie(t)})}function dL(e,t){return new e({type:"string",format:"ulid",check:"string_format",abort:!1,...Ie(t)})}function fL(e,t){return new e({type:"string",format:"xid",check:"string_format",abort:!1,...Ie(t)})}function hL(e,t){return new e({type:"string",format:"ksuid",check:"string_format",abort:!1,...Ie(t)})}function mL(e,t){return new e({type:"string",format:"ipv4",check:"string_format",abort:!1,...Ie(t)})}function pL(e,t){return new e({type:"string",format:"ipv6",check:"string_format",abort:!1,...Ie(t)})}function gL(e,t){return new e({type:"string",format:"cidrv4",check:"string_format",abort:!1,...Ie(t)})}function vL(e,t){return new e({type:"string",format:"cidrv6",check:"string_format",abort:!1,...Ie(t)})}function yL(e,t){return new e({type:"string",format:"base64",check:"string_format",abort:!1,...Ie(t)})}function bL(e,t){return new e({type:"string",format:"base64url",check:"string_format",abort:!1,...Ie(t)})}function xL(e,t){return new e({type:"string",format:"e164",check:"string_format",abort:!1,...Ie(t)})}function wL(e,t){return new e({type:"string",format:"jwt",check:"string_format",abort:!1,...Ie(t)})}function SL(e,t){return new e({type:"string",format:"datetime",check:"string_format",offset:!1,local:!1,precision:null,...Ie(t)})}function _L(e,t){return new e({type:"string",format:"date",check:"string_format",...Ie(t)})}function CL(e,t){return new e({type:"string",format:"time",check:"string_format",precision:null,...Ie(t)})}function EL(e,t){return new e({type:"string",format:"duration",check:"string_format",...Ie(t)})}function RL(e,t){return new e({type:"boolean",...Ie(t)})}function jL(e){return new e({type:"unknown"})}function TL(e,t){return new e({type:"never",...Ie(t)})}function wC(e,t){return new Q5({check:"max_length",...Ie(t),maximum:e})}function Tu(e,t){return new X5({check:"min_length",...Ie(t),minimum:e})}function SC(e,t){return new J5({check:"length_equals",...Ie(t),length:e})}function OL(e,t){return new W5({check:"string_format",format:"regex",...Ie(t),pattern:e})}function AL(e){return new e6({check:"string_format",format:"lowercase",...Ie(e)})}function ML(e){return new t6({check:"string_format",format:"uppercase",...Ie(e)})}function NL(e,t){return new n6({check:"string_format",format:"includes",...Ie(t),includes:e})}function DL(e,t){return new r6({check:"string_format",format:"starts_with",...Ie(t),prefix:e})}function kL(e,t){return new i6({check:"string_format",format:"ends_with",...Ie(t),suffix:e})}function eo(e){return new a6({check:"overwrite",tx:e})}function zL(e){return eo(t=>t.normalize(e))}function LL(){return eo(e=>e.trim())}function $L(){return eo(e=>e.toLowerCase())}function IL(){return eo(e=>e.toUpperCase())}function PL(){return eo(e=>W4(e))}function FL(e,t,r){return new e({type:"array",element:t,...Ie(r)})}function VL(e,t,r){return new e({type:"custom",check:"custom",fn:t,...Ie(r)})}function UL(e,t){const r=HL(a=>(a.addIssue=o=>{if(typeof o=="string")a.issues.push(gl(o,a.value,r._zod.def));else{const l=o;l.fatal&&(l.continue=!1),l.code??(l.code="custom"),l.input??(l.input=a.value),l.inst??(l.inst=r),l.continue??(l.continue=!r._zod.def.abort),a.issues.push(gl(l))}},e(a.value,a)),t);return r}function HL(e,t){const r=new Nr({check:"custom",...Ie(t)});return r._zod.check=e,r}function _C(e){let t=e?.target??"draft-2020-12";return t==="draft-4"&&(t="draft-04"),t==="draft-7"&&(t="draft-07"),{processors:e.processors??{},metadataRegistry:e?.metadata??tl,target:t,unrepresentable:e?.unrepresentable??"throw",override:e?.override??(()=>{}),io:e?.io??"output",counter:0,seen:new Map,cycles:e?.cycles??"ref",reused:e?.reused??"inline",external:e?.external??void 0}}function cn(e,t,r={path:[],schemaPath:[]}){var a;const o=e._zod.def,l=t.seen.get(e);if(l)return l.count++,r.schemaPath.includes(e)&&(l.cycle=r.path),l.schema;const u={schema:{},count:1,cycle:void 0,path:r.path};t.seen.set(e,u);const d=e._zod.toJSONSchema?.();if(d)u.schema=d;else{const y={...r,schemaPath:[...r.schemaPath,e],path:r.path};if(e._zod.processJSONSchema)e._zod.processJSONSchema(t,u.schema,y);else{const b=u.schema,x=t.processors[o.type];if(!x)throw new Error(`[toJSONSchema]: Non-representable type encountered: ${o.type}`);x(e,t,b,y)}const v=e._zod.parent;v&&(u.ref||(u.ref=v),cn(v,t,y),t.seen.get(v).isParent=!0)}const m=t.metadataRegistry.get(e);return m&&Object.assign(u.schema,m),t.io==="input"&&gn(e)&&(delete u.schema.examples,delete u.schema.default),t.io==="input"&&"_prefault"in u.schema&&((a=u.schema).default??(a.default=u.schema._prefault)),delete u.schema._prefault,t.seen.get(e).schema}function CC(e,t){const r=e.seen.get(t);if(!r)throw new Error("Unprocessed schema. This is a bug in Zod.");const a=new Map;for(const u of e.seen.entries()){const d=e.metadataRegistry.get(u[0])?.id;if(d){const m=a.get(d);if(m&&m!==u[0])throw new Error(`Duplicate schema id "${d}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);a.set(d,u[0])}}const o=u=>{const d=e.target==="draft-2020-12"?"$defs":"definitions";if(e.external){const v=e.external.registry.get(u[0])?.id,b=e.external.uri??(w=>w);if(v)return{ref:b(v)};const x=u[1].defId??u[1].schema.id??`schema${e.counter++}`;return u[1].defId=x,{defId:x,ref:`${b("__shared")}#/${d}/${x}`}}if(u[1]===r)return{ref:"#"};const p=`#/${d}/`,y=u[1].schema.id??`__schema${e.counter++}`;return{defId:y,ref:p+y}},l=u=>{if(u[1].schema.$ref)return;const d=u[1],{ref:m,defId:p}=o(u);d.def={...d.schema},p&&(d.defId=p);const y=d.schema;for(const v in y)delete y[v];y.$ref=m};if(e.cycles==="throw")for(const u of e.seen.entries()){const d=u[1];if(d.cycle)throw new Error(`Cycle detected: #/${d.cycle?.join("/")}/ -Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const u of e.seen.entries()){const d=u[1];if(t===u[0]){l(u);continue}if(e.external){const p=e.external.registry.get(u[0])?.id;if(t!==u[0]&&p){l(u);continue}}if(e.metadataRegistry.get(u[0])?.id){l(u);continue}if(d.cycle){l(u);continue}if(d.count>1&&e.reused==="ref"){l(u);continue}}}function EC(e,t){const r=e.seen.get(t);if(!r)throw new Error("Unprocessed schema. This is a bug in Zod.");const a=d=>{const m=e.seen.get(d);if(m.ref===null)return;const p=m.def??m.schema,y={...p},v=m.ref;if(m.ref=null,v){a(v);const x=e.seen.get(v),w=x.schema;if(w.$ref&&(e.target==="draft-07"||e.target==="draft-04"||e.target==="openapi-3.0")?(p.allOf=p.allOf??[],p.allOf.push(w)):Object.assign(p,w),Object.assign(p,y),d._zod.parent===v)for(const E in p)E==="$ref"||E==="allOf"||E in y||delete p[E];if(w.$ref&&x.def)for(const E in p)E==="$ref"||E==="allOf"||E in x.def&&JSON.stringify(p[E])===JSON.stringify(x.def[E])&&delete p[E]}const b=d._zod.parent;if(b&&b!==v){a(b);const x=e.seen.get(b);if(x?.schema.$ref&&(p.$ref=x.schema.$ref,x.def))for(const w in p)w==="$ref"||w==="allOf"||w in x.def&&JSON.stringify(p[w])===JSON.stringify(x.def[w])&&delete p[w]}e.override({zodSchema:d,jsonSchema:p,path:m.path??[]})};for(const d of[...e.seen.entries()].reverse())a(d[0]);const o={};if(e.target==="draft-2020-12"?o.$schema="https://json-schema.org/draft/2020-12/schema":e.target==="draft-07"?o.$schema="http://json-schema.org/draft-07/schema#":e.target==="draft-04"?o.$schema="http://json-schema.org/draft-04/schema#":e.target,e.external?.uri){const d=e.external.registry.get(t)?.id;if(!d)throw new Error("Schema is missing an `id` property");o.$id=e.external.uri(d)}Object.assign(o,r.def??r.schema);const l=e.metadataRegistry.get(t)?.id;l!==void 0&&o.id===l&&delete o.id;const u=e.external?.defs??{};for(const d of e.seen.entries()){const m=d[1];m.def&&m.defId&&(m.def.id===m.defId&&delete m.def.id,u[m.defId]=m.def)}e.external||Object.keys(u).length>0&&(e.target==="draft-2020-12"?o.$defs=u:o.definitions=u);try{const d=JSON.parse(JSON.stringify(o));return Object.defineProperty(d,"~standard",{value:{...t["~standard"],jsonSchema:{input:Ou(t,"input",e.processors),output:Ou(t,"output",e.processors)}},enumerable:!1,writable:!1}),d}catch{throw new Error("Error converting schema to JSON.")}}function gn(e,t){const r=t??{seen:new Set};if(r.seen.has(e))return!1;r.seen.add(e);const a=e._zod.def;if(a.type==="transform")return!0;if(a.type==="array")return gn(a.element,r);if(a.type==="set")return gn(a.valueType,r);if(a.type==="lazy")return gn(a.getter(),r);if(a.type==="promise"||a.type==="optional"||a.type==="nonoptional"||a.type==="nullable"||a.type==="readonly"||a.type==="default"||a.type==="prefault")return gn(a.innerType,r);if(a.type==="intersection")return gn(a.left,r)||gn(a.right,r);if(a.type==="record"||a.type==="map")return gn(a.keyType,r)||gn(a.valueType,r);if(a.type==="pipe")return e._zod.traits.has("$ZodCodec")?!0:gn(a.in,r)||gn(a.out,r);if(a.type==="object"){for(const o in a.shape)if(gn(a.shape[o],r))return!0;return!1}if(a.type==="union"){for(const o of a.options)if(gn(o,r))return!0;return!1}if(a.type==="tuple"){for(const o of a.items)if(gn(o,r))return!0;return!!(a.rest&&gn(a.rest,r))}return!1}const BL=(e,t={})=>r=>{const a=_C({...r,processors:t});return cn(e,a),CC(a,e),EC(a,e)},Ou=(e,t,r={})=>a=>{const{libraryOptions:o,target:l}=a??{},u=_C({...o??{},target:l,io:t,processors:r});return cn(e,u),CC(u,e),EC(u,e)},qL={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},GL=(e,t,r,a)=>{const o=r;o.type="string";const{minimum:l,maximum:u,format:d,patterns:m,contentEncoding:p}=e._zod.bag;if(typeof l=="number"&&(o.minLength=l),typeof u=="number"&&(o.maxLength=u),d&&(o.format=qL[d]??d,o.format===""&&delete o.format,d==="time"&&delete o.format),p&&(o.contentEncoding=p),m&&m.size>0){const y=[...m];y.length===1?o.pattern=y[0].source:y.length>1&&(o.allOf=[...y.map(v=>({...t.target==="draft-07"||t.target==="draft-04"||t.target==="openapi-3.0"?{type:"string"}:{},pattern:v.source}))])}},ZL=(e,t,r,a)=>{r.type="boolean"},KL=(e,t,r,a)=>{r.not={}},YL=(e,t,r,a)=>{},QL=(e,t,r,a)=>{const o=e._zod.def,l=cC(o.entries);l.every(u=>typeof u=="number")&&(r.type="number"),l.every(u=>typeof u=="string")&&(r.type="string"),r.enum=l},XL=(e,t,r,a)=>{if(t.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},JL=(e,t,r,a)=>{if(t.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},WL=(e,t,r,a)=>{const o=r,l=e._zod.def,{minimum:u,maximum:d}=e._zod.bag;typeof u=="number"&&(o.minItems=u),typeof d=="number"&&(o.maxItems=d),o.type="array",o.items=cn(l.element,t,{...a,path:[...a.path,"items"]})},e8=(e,t,r,a)=>{const o=r,l=e._zod.def;o.type="object",o.properties={};const u=l.shape;for(const p in u)o.properties[p]=cn(u[p],t,{...a,path:[...a.path,"properties",p]});const d=new Set(Object.keys(u)),m=new Set([...d].filter(p=>{const y=l.shape[p]._zod;return t.io==="input"?y.optin===void 0:y.optout===void 0}));m.size>0&&(o.required=Array.from(m)),l.catchall?._zod.def.type==="never"?o.additionalProperties=!1:l.catchall?l.catchall&&(o.additionalProperties=cn(l.catchall,t,{...a,path:[...a.path,"additionalProperties"]})):t.io==="output"&&(o.additionalProperties=!1)},t8=(e,t,r,a)=>{const o=e._zod.def,l=o.inclusive===!1,u=o.options.map((d,m)=>cn(d,t,{...a,path:[...a.path,l?"oneOf":"anyOf",m]}));l?r.oneOf=u:r.anyOf=u},n8=(e,t,r,a)=>{const o=e._zod.def,l=cn(o.left,t,{...a,path:[...a.path,"allOf",0]}),u=cn(o.right,t,{...a,path:[...a.path,"allOf",1]}),d=p=>"allOf"in p&&Object.keys(p).length===1,m=[...d(l)?l.allOf:[l],...d(u)?u.allOf:[u]];r.allOf=m},r8=(e,t,r,a)=>{const o=e._zod.def,l=cn(o.innerType,t,a),u=t.seen.get(e);t.target==="openapi-3.0"?(u.ref=o.innerType,r.nullable=!0):r.anyOf=[l,{type:"null"}]},i8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType},a8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType,r.default=JSON.parse(JSON.stringify(o.defaultValue))},s8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType,t.io==="input"&&(r._prefault=JSON.parse(JSON.stringify(o.defaultValue)))},o8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType;let u;try{u=o.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}r.default=u},l8=(e,t,r,a)=>{const o=e._zod.def,l=o.in._zod.traits.has("$ZodTransform"),u=t.io==="input"?l?o.out:o.in:o.out;cn(u,t,a);const d=t.seen.get(e);d.ref=u},c8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType,r.readOnly=!0},RC=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType};function Xm(){return Xm=Object.assign?Object.assign.bind():function(e){for(var t=1;t0){var m=o.errors[0][0];r[d]={message:m.message,type:m.code}}else r[d]={message:u,type:l};if(o.code==="invalid_union"&&o.errors.forEach(function(v){return v.forEach(function(b){return e.push(Xm({},b,{path:[].concat(o.path,b.path)}))})}),t){var p=r[d].types,y=p&&p[o.code];r[d]=og(d,t,r,l,y?[].concat(y,o.message):o.message)}e.shift()};e.length;)a();return r}function gg(e,t,r){if(r===void 0&&(r={}),(function(a){return"_def"in a&&typeof a._def=="object"&&"typeName"in a._def})(e))return function(a,o,l){try{return Promise.resolve(Qx(function(){return Promise.resolve(e[r.mode==="sync"?"parse":"parseAsync"](a,t)).then(function(u){return l.shouldUseNativeValidation&&Km({},l),{errors:{},values:r.raw?Object.assign({},a):u}})},function(u){if((function(d){return Array.isArray(d?.issues)})(u))return{values:{},errors:kx(u8(u.errors,!l.shouldUseNativeValidation&&l.criteriaMode==="all"),l)};throw u}))}catch(u){return Promise.reject(u)}};if((function(a){return"_zod"in a&&typeof a._zod=="object"})(e))return function(a,o,l){try{return Promise.resolve(Qx(function(){return Promise.resolve((r.mode==="sync"?h5:m5)(e,a,t)).then(function(u){return l.shouldUseNativeValidation&&Km({},l),{errors:{},values:r.raw?Object.assign({},a):u}})},function(u){if((function(d){return d instanceof mg})(u))return{values:{},errors:kx(d8(u.issues,!l.shouldUseNativeValidation&&l.criteriaMode==="all"),l)};throw u}))}catch(u){return Promise.reject(u)}};throw new Error("Invalid input: not a Zod schema")}const f8=me("ZodISODateTime",(e,t)=>{b6.init(e,t),Et.init(e,t)});function h8(e){return SL(f8,e)}const m8=me("ZodISODate",(e,t)=>{x6.init(e,t),Et.init(e,t)});function p8(e){return _L(m8,e)}const g8=me("ZodISOTime",(e,t)=>{w6.init(e,t),Et.init(e,t)});function v8(e){return CL(g8,e)}const y8=me("ZodISODuration",(e,t)=>{S6.init(e,t),Et.init(e,t)});function b8(e){return EL(y8,e)}const x8=(e,t)=>{mg.init(e,t),e.name="ZodError",Object.defineProperties(e,{format:{value:r=>f5(e,r)},flatten:{value:r=>d5(e,r)},addIssue:{value:r=>{e.issues.push(r),e.message=JSON.stringify(e.issues,Ym,2)}},addIssues:{value:r=>{e.issues.push(...r),e.message=JSON.stringify(e.issues,Ym,2)}},isEmpty:{get(){return e.issues.length===0}}})},nr=me("ZodError",x8,{Parent:Error}),w8=od(nr),S8=ld(nr),_8=cd(nr),C8=ud(nr),E8=v5(nr),R8=y5(nr),j8=b5(nr),T8=x5(nr),O8=w5(nr),A8=S5(nr),M8=_5(nr),N8=C5(nr),Xx=new WeakMap;function fd(e,t,r){const a=Object.getPrototypeOf(e);let o=Xx.get(a);if(o||(o=new Set,Xx.set(a,o)),!o.has(t)){o.add(t);for(const l in r){const u=r[l];Object.defineProperty(a,l,{configurable:!0,enumerable:!1,get(){const d=u.bind(this);return Object.defineProperty(this,l,{configurable:!0,writable:!0,enumerable:!0,value:d}),d},set(d){Object.defineProperty(this,l,{configurable:!0,writable:!0,enumerable:!0,value:d})}})}}}const Ut=me("ZodType",(e,t)=>(Vt.init(e,t),Object.assign(e["~standard"],{jsonSchema:{input:Ou(e,"input"),output:Ou(e,"output")}}),e.toJSONSchema=BL(e,{}),e.def=t,e.type=t.type,Object.defineProperty(e,"_def",{value:t}),e.parse=(r,a)=>w8(e,r,a,{callee:e.parse}),e.safeParse=(r,a)=>_8(e,r,a),e.parseAsync=async(r,a)=>S8(e,r,a,{callee:e.parseAsync}),e.safeParseAsync=async(r,a)=>C8(e,r,a),e.spa=e.safeParseAsync,e.encode=(r,a)=>E8(e,r,a),e.decode=(r,a)=>R8(e,r,a),e.encodeAsync=async(r,a)=>j8(e,r,a),e.decodeAsync=async(r,a)=>T8(e,r,a),e.safeEncode=(r,a)=>O8(e,r,a),e.safeDecode=(r,a)=>A8(e,r,a),e.safeEncodeAsync=async(r,a)=>M8(e,r,a),e.safeDecodeAsync=async(r,a)=>N8(e,r,a),fd(e,"ZodType",{check(...r){const a=this.def;return this.clone(Wi(a,{checks:[...a.checks??[],...r.map(o=>typeof o=="function"?{_zod:{check:o,def:{check:"custom"},onattach:[]}}:o)]}),{parent:!0})},with(...r){return this.check(...r)},clone(r,a){return ea(this,r,a)},brand(){return this},register(r,a){return r.add(this,a),this},refine(r,a){return this.check(E$(r,a))},superRefine(r,a){return this.check(R$(r,a))},overwrite(r){return this.check(eo(r))},optional(){return tw(this)},exactOptional(){return f$(this)},nullable(){return nw(this)},nullish(){return tw(nw(this))},nonoptional(r){return y$(this,r)},array(){return n$(this)},or(r){return a$([this,r])},and(r){return o$(this,r)},transform(r){return rw(this,u$(r))},default(r){return p$(this,r)},prefault(r){return v$(this,r)},catch(r){return x$(this,r)},pipe(r){return rw(this,r)},readonly(){return _$(this)},describe(r){const a=this.clone();return tl.add(a,{description:r}),a},meta(...r){if(r.length===0)return tl.get(this);const a=this.clone();return tl.add(a,r[0]),a},isOptional(){return this.safeParse(void 0).success},isNullable(){return this.safeParse(null).success},apply(r){return r(this)}}),Object.defineProperty(e,"description",{get(){return tl.get(e)?.description},configurable:!0}),e)),jC=me("_ZodString",(e,t)=>{pg.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(a,o,l)=>GL(e,a,o);const r=e._zod.bag;e.format=r.format??null,e.minLength=r.minimum??null,e.maxLength=r.maximum??null,fd(e,"_ZodString",{regex(...a){return this.check(OL(...a))},includes(...a){return this.check(NL(...a))},startsWith(...a){return this.check(DL(...a))},endsWith(...a){return this.check(kL(...a))},min(...a){return this.check(Tu(...a))},max(...a){return this.check(wC(...a))},length(...a){return this.check(SC(...a))},nonempty(...a){return this.check(Tu(1,...a))},lowercase(a){return this.check(AL(a))},uppercase(a){return this.check(ML(a))},trim(){return this.check(LL())},normalize(...a){return this.check(zL(...a))},toLowerCase(){return this.check($L())},toUpperCase(){return this.check(IL())},slugify(){return this.check(PL())}})}),D8=me("ZodString",(e,t)=>{pg.init(e,t),jC.init(e,t),e.email=r=>e.check(tL(k8,r)),e.url=r=>e.check(sL(z8,r)),e.jwt=r=>e.check(wL(Q8,r)),e.emoji=r=>e.check(oL(L8,r)),e.guid=r=>e.check(Yx(Jx,r)),e.uuid=r=>e.check(nL(au,r)),e.uuidv4=r=>e.check(rL(au,r)),e.uuidv6=r=>e.check(iL(au,r)),e.uuidv7=r=>e.check(aL(au,r)),e.nanoid=r=>e.check(lL($8,r)),e.guid=r=>e.check(Yx(Jx,r)),e.cuid=r=>e.check(cL(I8,r)),e.cuid2=r=>e.check(uL(P8,r)),e.ulid=r=>e.check(dL(F8,r)),e.base64=r=>e.check(yL(Z8,r)),e.base64url=r=>e.check(bL(K8,r)),e.xid=r=>e.check(fL(V8,r)),e.ksuid=r=>e.check(hL(U8,r)),e.ipv4=r=>e.check(mL(H8,r)),e.ipv6=r=>e.check(pL(B8,r)),e.cidrv4=r=>e.check(gL(q8,r)),e.cidrv6=r=>e.check(vL(G8,r)),e.e164=r=>e.check(xL(Y8,r)),e.datetime=r=>e.check(h8(r)),e.date=r=>e.check(p8(r)),e.time=r=>e.check(v8(r)),e.duration=r=>e.check(b8(r))});function fu(e){return eL(D8,e)}const Et=me("ZodStringFormat",(e,t)=>{St.init(e,t),jC.init(e,t)}),k8=me("ZodEmail",(e,t)=>{u6.init(e,t),Et.init(e,t)}),Jx=me("ZodGUID",(e,t)=>{l6.init(e,t),Et.init(e,t)}),au=me("ZodUUID",(e,t)=>{c6.init(e,t),Et.init(e,t)}),z8=me("ZodURL",(e,t)=>{d6.init(e,t),Et.init(e,t)}),L8=me("ZodEmoji",(e,t)=>{f6.init(e,t),Et.init(e,t)}),$8=me("ZodNanoID",(e,t)=>{h6.init(e,t),Et.init(e,t)}),I8=me("ZodCUID",(e,t)=>{m6.init(e,t),Et.init(e,t)}),P8=me("ZodCUID2",(e,t)=>{p6.init(e,t),Et.init(e,t)}),F8=me("ZodULID",(e,t)=>{g6.init(e,t),Et.init(e,t)}),V8=me("ZodXID",(e,t)=>{v6.init(e,t),Et.init(e,t)}),U8=me("ZodKSUID",(e,t)=>{y6.init(e,t),Et.init(e,t)}),H8=me("ZodIPv4",(e,t)=>{_6.init(e,t),Et.init(e,t)}),B8=me("ZodIPv6",(e,t)=>{C6.init(e,t),Et.init(e,t)}),q8=me("ZodCIDRv4",(e,t)=>{E6.init(e,t),Et.init(e,t)}),G8=me("ZodCIDRv6",(e,t)=>{R6.init(e,t),Et.init(e,t)}),Z8=me("ZodBase64",(e,t)=>{j6.init(e,t),Et.init(e,t)}),K8=me("ZodBase64URL",(e,t)=>{O6.init(e,t),Et.init(e,t)}),Y8=me("ZodE164",(e,t)=>{A6.init(e,t),Et.init(e,t)}),Q8=me("ZodJWT",(e,t)=>{N6.init(e,t),Et.init(e,t)}),X8=me("ZodBoolean",(e,t)=>{D6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>ZL(e,r,a)});function Wx(e){return RL(X8,e)}const J8=me("ZodUnknown",(e,t)=>{k6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>YL()});function ew(){return jL(J8)}const W8=me("ZodNever",(e,t)=>{z6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>KL(e,r,a)});function e$(e){return TL(W8,e)}const t$=me("ZodArray",(e,t)=>{L6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>WL(e,r,a,o),e.element=t.element,fd(e,"ZodArray",{min(r,a){return this.check(Tu(r,a))},nonempty(r){return this.check(Tu(1,r))},max(r,a){return this.check(wC(r,a))},length(r,a){return this.check(SC(r,a))},unwrap(){return this.element}})});function n$(e,t){return FL(t$,e,t)}const r$=me("ZodObject",(e,t)=>{I6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>e8(e,r,a,o),pt(e,"shape",()=>t.shape),fd(e,"ZodObject",{keyof(){return l$(Object.keys(this._zod.def.shape))},catchall(r){return this.clone({...this._zod.def,catchall:r})},passthrough(){return this.clone({...this._zod.def,catchall:ew()})},loose(){return this.clone({...this._zod.def,catchall:ew()})},strict(){return this.clone({...this._zod.def,catchall:e$()})},strip(){return this.clone({...this._zod.def,catchall:void 0})},extend(r){return a5(this,r)},safeExtend(r){return s5(this,r)},merge(r){return o5(this,r)},pick(r){return r5(this,r)},omit(r){return i5(this,r)},partial(...r){return l5(TC,this,r[0])},required(...r){return c5(OC,this,r[0])}})});function vg(e,t){const r={type:"object",shape:e??{},...Ie(t)};return new r$(r)}const i$=me("ZodUnion",(e,t)=>{P6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>t8(e,r,a,o),e.options=t.options});function a$(e,t){return new i$({type:"union",options:e,...Ie(t)})}const s$=me("ZodIntersection",(e,t)=>{F6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>n8(e,r,a,o)});function o$(e,t){return new s$({type:"intersection",left:e,right:t})}const Jm=me("ZodEnum",(e,t)=>{V6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(a,o,l)=>QL(e,a,o),e.enum=t.entries,e.options=Object.values(t.entries);const r=new Set(Object.keys(t.entries));e.extract=(a,o)=>{const l={};for(const u of a)if(r.has(u))l[u]=t.entries[u];else throw new Error(`Key ${u} not found in enum`);return new Jm({...t,checks:[],...Ie(o),entries:l})},e.exclude=(a,o)=>{const l={...t.entries};for(const u of a)if(r.has(u))delete l[u];else throw new Error(`Key ${u} not found in enum`);return new Jm({...t,checks:[],...Ie(o),entries:l})}});function l$(e,t){const r=Array.isArray(e)?Object.fromEntries(e.map(a=>[a,a])):e;return new Jm({type:"enum",entries:r,...Ie(t)})}const c$=me("ZodTransform",(e,t)=>{U6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>JL(e,r),e._zod.parse=(r,a)=>{if(a.direction==="backward")throw new lC(e.constructor.name);r.addIssue=l=>{if(typeof l=="string")r.issues.push(gl(l,r.value,t));else{const u=l;u.fatal&&(u.continue=!1),u.code??(u.code="custom"),u.input??(u.input=r.value),u.inst??(u.inst=e),r.issues.push(gl(u))}};const o=t.transform(r.value,r);return o instanceof Promise?o.then(l=>(r.value=l,r.fallback=!0,r)):(r.value=o,r.fallback=!0,r)}});function u$(e){return new c$({type:"transform",transform:e})}const TC=me("ZodOptional",(e,t)=>{xC.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>RC(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function tw(e){return new TC({type:"optional",innerType:e})}const d$=me("ZodExactOptional",(e,t)=>{H6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>RC(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function f$(e){return new d$({type:"optional",innerType:e})}const h$=me("ZodNullable",(e,t)=>{B6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>r8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function nw(e){return new h$({type:"nullable",innerType:e})}const m$=me("ZodDefault",(e,t)=>{q6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>a8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType,e.removeDefault=e.unwrap});function p$(e,t){return new m$({type:"default",innerType:e,get defaultValue(){return typeof t=="function"?t():dC(t)}})}const g$=me("ZodPrefault",(e,t)=>{G6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>s8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function v$(e,t){return new g$({type:"prefault",innerType:e,get defaultValue(){return typeof t=="function"?t():dC(t)}})}const OC=me("ZodNonOptional",(e,t)=>{Z6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>i8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function y$(e,t){return new OC({type:"nonoptional",innerType:e,...Ie(t)})}const b$=me("ZodCatch",(e,t)=>{K6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>o8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType,e.removeCatch=e.unwrap});function x$(e,t){return new b$({type:"catch",innerType:e,catchValue:typeof t=="function"?t:()=>t})}const w$=me("ZodPipe",(e,t)=>{Y6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>l8(e,r,a,o),e.in=t.in,e.out=t.out});function rw(e,t){return new w$({type:"pipe",in:e,out:t})}const S$=me("ZodReadonly",(e,t)=>{Q6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>c8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function _$(e){return new S$({type:"readonly",innerType:e})}const C$=me("ZodCustom",(e,t)=>{X6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>XL(e,r)});function E$(e,t={}){return VL(C$,e,t)}function R$(e,t){return UL(e,t)}const j$=/\.(md|markdown)$/i,T$=/\.(png|jpe?g|gif|svg|webp|ico|bmp|avif)$/i,AC=/\.html?$/i,MC=/\.pdf$/i,O$=/\.(csv|tsv)$/i,A$=/\.(txt|log|json|ya?ml|toml|csv|go|py|js|ts|jsx|tsx|sh|bash|zsh|rb|rs|c|h|cpp|java|kt|swift|sql|css|xml|ini|conf|env|mod|sum|jsonl)$/i;function yg(e){if(e<1024)return e+" B";const t=["KB","MB","GB","TB"];let r=-1;do e/=1024,r++;while(e>=1024&&ra.path.toLowerCase()===r||a.path.toLowerCase()===r+".md")||t.find(a=>{const o=a.name.toLowerCase();return o===r||o===r+".md"})}async function Na(e){try{if(navigator.clipboard)return await navigator.clipboard.writeText(e),!0}catch{}return!1}const DC="bdrive.lastProject";function N$(){try{return localStorage.getItem(DC)||""}catch{return""}}function D$(e){try{localStorage.setItem(DC,e)}catch{}}function hd(e){return e.user_name?`${e.user_name} <${e.user}>`:e.user||e.author||"unknown"}function k$({className:e,...t}){return f.jsx("div",{"data-slot":"table-container",className:"relative w-full overflow-x-auto",children:f.jsx("table",{"data-slot":"table",className:We("w-full caption-bottom text-sm",e),...t})})}function z$({className:e,...t}){return f.jsx("thead",{"data-slot":"table-header",className:We("[&_tr]:border-b",e),...t})}function L$({className:e,...t}){return f.jsx("tbody",{"data-slot":"table-body",className:We("[&_tr:last-child]:border-0",e),...t})}function iw({className:e,...t}){return f.jsx("tr",{"data-slot":"table-row",className:We("border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",e),...t})}function aw({className:e,...t}){return f.jsx("th",{"data-slot":"table-head",className:We("h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...t})}function $$({className:e,...t}){return f.jsx("td",{"data-slot":"table-cell",className:We("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...t})}function I$({header:e}){const t=e.column.getIsSorted();return e.column.getCanSort()?f.jsx(aw,{"data-sort":t||void 0,"aria-sort":t==="asc"?"ascending":t==="desc"?"descending":"none",children:f.jsxs("button",{type:"button",className:"th-sort",onClick:e.column.getToggleSortingHandler(),children:[Bm(e.column.columnDef.header,e.getContext()),t==="asc"?" ↑":t==="desc"?" ↓":""]})}):f.jsx(aw,{children:Bm(e.column.columnDef.header,e.getContext())})}function kC({table:e,className:t}){return f.jsx("div",{className:"admin-list admin-card-table"+(t?" "+t:""),children:f.jsxs(k$,{className:"admin-table",children:[f.jsx(z$,{children:e.getHeaderGroups().map(r=>f.jsx(iw,{children:r.headers.map(a=>f.jsx(I$,{header:a},a.id))},r.id))}),f.jsx(L$,{children:e.getRowModel().rows.map(r=>f.jsx(iw,{className:"admin-item",children:r.getVisibleCells().map(a=>f.jsx($$,{children:Bm(a.column.columnDef.cell,a.getContext())},a.id))},r.id))})]})})}function zC(e){return e?"expires "+new Date(e).toLocaleDateString():"no expiry"}function P$(e){if(e.opens===void 0)return null;if(e.opens===0)return"not opened yet";const t=`${e.opens} open${e.opens===1?"":"s"}`;return e.last_opened?`${t} · last opened ${new Date(e.last_opened).toLocaleDateString()}`:t}function LC(e,t){const r=[];t&&e.project_name&&r.push(e.project_name),e.creator&&r.push("by "+e.creator),e.created&&r.push(new Date(e.created).toLocaleDateString()),r.push(zC(e.expires));const a=P$(e);return a&&r.push(a),r.join(" · ")}const $C="Opens count how many times a file has been read through a public link. Repeat opens by the same reader within 10 minutes count once.";function IC({shares:e,onChanged:t,showProject:r=!1,canRevoke:a=!0,empty:o="No public shares.",loading:l=!1}){const[u,d]=S.useState([]),m=S.useMemo(()=>L_(),[]),p=S.useMemo(()=>[m.accessor("path",{header:"Path",cell:v=>f.jsx("a",{className:"ai-main mono",title:v.getValue(),...Qs(Oa(v.getValue(),v.row.original.project)),children:v.getValue()})}),m.accessor(v=>LC(v,r),{id:"detail",header:r?"Project":"Shared",cell:v=>f.jsx("span",{className:"ai-tag",children:v.getValue()})}),m.display({id:"actions",header:"",cell:v=>f.jsxs("span",{className:"share-acts",children:[f.jsx("button",{className:"ai-btn","aria-label":`Copy the public link to ${v.row.original.path}`,title:"Copy link",onClick:()=>Na(v.row.original.url).then(b=>qe(b?"Copied.":"Select and copy the link.")),children:f.jsx(nt,{name:"copy"})}),a&&f.jsx("button",{className:"ai-del","aria-label":`Revoke the share of ${v.row.original.path}`,onClick:()=>PC(v.row.original,t),children:"Revoke"})]})})],[m,t,r,a]),y=K_({data:e,columns:p,state:{sorting:u},onSortingChange:d,getCoreRowModel:G_(),getSortedRowModel:Z_()});return l?f.jsx("div",{className:"admin-list",children:f.jsx("div",{className:"admin-empty",children:"Loading…"})}):e.length===0?f.jsx("div",{className:"admin-list",children:f.jsx("div",{className:"admin-empty",children:o})}):f.jsx(kC,{table:y,className:"shares-table"})}async function PC(e,t){if(await zi("Revoke share link",`Revoke the public link to “${e.path}”? Anyone with the URL will lose access.`,"Revoke",!0))try{await Wn("DELETE","/api/shares/"+e.token),qe("Share revoked."),t()}catch(r){qe(r.message,!0)}}const F$=vg({name:fu().trim().min(1,"Give the organization a name.").max(60,"Keep it under 60 characters.")});function V$({org:e,projects:t,myEmail:r}){const a=ka(),o=e.role==="owner",l=()=>a.invalidateQueries({queryKey:["orgs"]}),u=()=>a.invalidateQueries({queryKey:["invites",e.id]}),d=()=>a.invalidateQueries({queryKey:["orgShares",e.id]}),m=lg({resolver:gg(F$),values:{name:e.name}}),{data:p}=Ft({queryKey:["invites",e.id],queryFn:()=>qt(`/api/orgs/${e.id}/invites`),enabled:o,select:x=>x.invites||[]}),{data:y,isLoading:v}=Ft({queryKey:["orgShares",e.id],queryFn:()=>qt(`/api/orgs/${e.id}/shares`),enabled:o,select:x=>x.shares||[]}),b=t.filter(x=>x.org===e.id);return f.jsxs("div",{className:"admin",children:[f.jsx("h1",{id:"org-title",children:e.name}),!o&&f.jsx("p",{className:"role-chip-row",children:f.jsx("span",{className:"ai-tag role-chip",children:"Member"})}),!o&&f.jsx("p",{className:"admin-sub",children:"Only owners can rename this organization, manage members, or issue invite links."}),o&&f.jsxs("form",{className:"admin-row",onSubmit:m.handleSubmit(async({name:x})=>{try{await Wn("PATCH","/api/orgs/"+e.id,{name:x}),qe("Renamed."),l()}catch(w){qe(w.message,!0)}}),children:[f.jsx("label",{className:"admin-lbl",htmlFor:"org-rename",children:"Organization name"}),f.jsx("input",{id:"org-rename",type:"text","aria-invalid":!!m.formState.errors.name,"aria-describedby":m.formState.errors.name?"org-rename-err":void 0,...m.register("name")}),f.jsx(xt,{variant:"subtle",id:"org-rename-btn",type:"submit",disabled:!m.formState.isDirty,children:"Rename org"}),m.formState.errors.name&&f.jsx("span",{id:"org-rename-err",role:"alert",className:"field-err",children:m.formState.errors.name.message})]}),f.jsx("h3",{children:"Members"}),f.jsx(U$,{org:e,owner:o,myEmail:r,onChanged:l}),f.jsx("h3",{children:"Projects"}),f.jsxs("div",{className:"admin-list",children:[b.length===0&&f.jsx("div",{className:"admin-empty",children:"No projects yet."}),b.map(x=>f.jsx("div",{className:"admin-item",children:f.jsx("span",{className:"ai-main",title:x.name,children:x.name})},x.id))]}),o&&f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"admin-h",children:[f.jsx("h3",{children:"Invite links"}),f.jsx(xt,{variant:"primary",onClick:async()=>{try{const x=await ei(`/api/orgs/${e.id}/invites`),w=await Na(x.url);qe(w?"Invite link copied to clipboard.":"Invite created — copy it from the list below."),u()}catch(x){qe(x.message,!0)}},children:"New invite"})]}),f.jsxs("div",{className:"admin-list",children:[p&&p.length===0&&f.jsx("div",{className:"admin-empty",children:"No active invite links."}),(p||[]).map(x=>f.jsxs("div",{className:"admin-item",children:[f.jsx("button",{type:"button",className:"ai-main mono ai-copy","aria-label":`Copy invite link ${x.url}`,title:x.url,onClick:()=>Na(x.url).then(w=>qe(w?"Copied.":"Select and copy the link.")),children:x.url}),f.jsx("span",{className:"ai-tag",children:(x.creator?"by "+x.creator+" · ":"")+(x.uses?x.uses+" joined · ":"unused · ")+"expires "+new Date(x.expires).toLocaleDateString()}),f.jsx("button",{className:"ai-del","aria-label":`Revoke invite ${x.token.slice(0,8)}`,onClick:async()=>{if(await zi("Revoke invite",`Revoke the link starting ${x.token.slice(0,8)}…? Anyone still holding it won't be able to join.`,"Revoke",!0))try{await Wn("DELETE",`/api/orgs/${e.id}/invites/${x.token}`),qe("Revoked."),u()}catch(w){qe(w.message,!0)}},children:"Revoke"})]},x.token))]}),f.jsx("h3",{children:"Public share links"}),f.jsx("p",{className:"admin-sub",children:"Every live link across this organization's projects. A project's own links are on its Settings page, and on the file itself."}),f.jsx(IC,{shares:y||[],loading:v,onChanged:d,showProject:!0})]})]})}function U$({org:e,owner:t,myEmail:r,onChanged:a}){const[o,l]=S.useState([{id:"email",desc:!1}]),u=S.useMemo(()=>L_(),[]),d=S.useMemo(()=>[u.accessor("email",{id:"email",header:"Member",cell:p=>{const y=!!r&&p.getValue().toLowerCase()===r.toLowerCase();return f.jsx("span",{className:"ai-main",title:p.getValue(),children:p.getValue()+(y?" (you)":"")})}}),u.accessor("role",{id:"role",header:"Role",cell:p=>{const y=p.row.original,v=!!r&&y.email.toLowerCase()===r.toLowerCase();return!t||v?f.jsx("span",{className:"ai-tag role-static",children:y.role}):f.jsxs("span",{className:"role-cell",children:[f.jsxs("select",{"aria-label":`Role for ${y.email}`,value:y.role,onChange:async b=>{try{await Wn("PATCH",`/api/orgs/${e.id}/members/${encodeURIComponent(y.email)}`,{role:b.target.value}),qe("Role updated.")}catch(x){qe(x.message,!0)}a()},children:[f.jsx("option",{value:"owner",children:"owner"}),f.jsx("option",{value:"member",children:"member"})]}),f.jsx("button",{className:"ai-del","aria-label":`Remove ${y.email}`,onClick:async()=>{if(await zi("Remove member",`Remove ${y.email} from ${e.name}?`,"Remove",!0))try{await Wn("DELETE",`/api/orgs/${e.id}/members/${encodeURIComponent(y.email)}`),qe("Removed."),a()}catch(b){qe(b.message,!0)}},children:"Remove"})]})}})],[u,e.id,e.name,t,r]),m=K_({data:e.members,columns:d,state:{sorting:o},onSortingChange:l,getCoreRowModel:G_(),getSortedRowModel:Z_()});return f.jsx(kC,{table:m})}const H$=vg({require_verification:Wx(),require_approval:Wx()});function B$(){const e=ka(),{data:t,error:r}=Ft({queryKey:["admin","policy"],queryFn:()=>qt("/api/admin/policy")}),{data:a}=A_(!0),o=lg({resolver:gg(H$),values:t?{require_verification:t.require_verification&&t.mailer,require_approval:t.require_approval}:{require_verification:!1,require_approval:!1}});if(S.useEffect(()=>{r&&qe(r.message,!0)},[r]),!t)return null;const l=async(u,d,m)=>{try{await ei(`/api/admin/pending/${u}/${d}`),qe((d==="approve"?"Approved ":"Denied ")+m),e.invalidateQueries({queryKey:["admin","pending"]})}catch(p){qe(p.message,!0)}};return f.jsxs("div",{className:"admin",children:[f.jsx("h1",{children:"Signup & access"}),f.jsx("p",{className:"admin-sub",children:"Who can create an account on this hub, and how new accounts are vetted."}),f.jsx("h3",{children:"New-account vetting"}),f.jsxs("form",{onSubmit:o.handleSubmit(async u=>{try{await ei("/api/admin/policy",u),qe("Signup policy saved."),e.invalidateQueries({queryKey:["admin","policy"]})}catch(d){qe(d.message,!0)}}),children:[f.jsxs("div",{className:"admin-list",children:[f.jsx(sw,{label:"Require email verification",desc:t.mailer?"New accounts must click an emailed link before they can sign in — proves they control the address.":"Configure SMTP on the server (auth.smtp) to enable email verification.",disabled:!t.mailer,inputProps:o.register("require_verification")}),f.jsx(sw,{label:"Require admin approval",desc:"New accounts wait for a hub admin to approve them before they gain access.",inputProps:o.register("require_approval")})]}),f.jsx(xt,{variant:"primary",type:"submit",style:{marginTop:14},disabled:!o.formState.isDirty,children:"Save policy"})]}),f.jsx("h3",{children:"Who can sign up"}),f.jsxs("div",{className:"admin-list",children:[f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:"Allowed email domains"}),f.jsx("span",{className:"ai-tag",children:t.allowed_domains&&t.allowed_domains.length?t.allowed_domains.map(u=>"@"+u).join(", "):"any"})]}),f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:"Self-signup"}),f.jsx("span",{className:"ai-tag",children:t.allow_signup?"open":"invite-only"})]}),f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:"Hub admins"}),f.jsx("span",{className:"ai-tag",children:t.admins&&t.admins.length?t.admins.join(", "):"none"})]})]}),f.jsx("p",{className:"admin-sub",children:"Domains and admins are set in the server config file (they can't be widened from the browser)."}),f.jsx("h3",{children:"Pending signups"}),f.jsxs("div",{className:"admin-list",children:[(!a||a.length===0)&&f.jsx("div",{className:"admin-empty",children:"No one is waiting for approval."}),(a||[]).map(u=>f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:(u.name?u.name+" · ":"")+u.email}),f.jsx(xt,{variant:"primary",onClick:()=>l(u.id,"approve",u.email),children:"Approve"}),f.jsx("button",{className:"ai-del",onClick:()=>l(u.id,"deny",u.email),children:"Deny"})]},u.id))]})]})}function sw({label:e,desc:t,disabled:r,inputProps:a}){return f.jsxs("label",{className:"admin-item toggle",style:r?{opacity:.55}:void 0,children:[f.jsxs("span",{className:"ai-main",children:[f.jsx("div",{className:"tg-label",children:e}),f.jsx("div",{className:"tg-desc",children:t})]}),f.jsx("input",{type:"checkbox",disabled:r,...a})]})}function q$({...e}){return f.jsx(m1,{"data-slot":"select",...e})}function G$({...e}){return f.jsx(y1,{"data-slot":"select-value",...e})}function Z$({className:e,size:t="default",children:r,...a}){return f.jsxs(g1,{"data-slot":"select-trigger","data-size":t,className:We("flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",e),...a,children:[r,f.jsx(b1,{asChild:!0,children:f.jsx(Kp,{className:"size-4 opacity-50"})})]})}function K$({className:e,children:t,position:r="item-aligned",align:a="center",...o}){return f.jsx(w1,{children:f.jsxs(S1,{"data-slot":"select-content",className:We("relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",r==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",e),position:r,align:a,...o,children:[f.jsx(Q$,{}),f.jsx(j1,{className:We("p-1",r==="popper"&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"),children:t}),f.jsx(X$,{})]})})}function Y$({className:e,children:t,...r}){return f.jsxs(M1,{"data-slot":"select-item",className:We("relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",e),...r,children:[f.jsx("span",{"data-slot":"select-item-indicator",className:"absolute right-2 flex size-3.5 items-center justify-center",children:f.jsx(k1,{children:f.jsx(g_,{className:"size-4"})})}),f.jsx(N1,{children:t})]})}function Q$({className:e,...t}){return f.jsx(z1,{"data-slot":"select-scroll-up-button",className:We("flex cursor-default items-center justify-center py-1",e),...t,children:f.jsx(vk,{className:"size-4"})})}function X$({className:e,...t}){return f.jsx(L1,{"data-slot":"select-scroll-down-button",className:We("flex cursor-default items-center justify-center py-1",e),...t,children:f.jsx(Kp,{className:"size-4"})})}const ow=["#5b8def","#f5a623","#4cc38a","#e0679b","#8b7bf0","#3ec8c8","#e6934a"];function vl(e){let t=0;for(const r of e)t=t*31+r.charCodeAt(0)>>>0;return ow[t%ow.length]}function rm({projects:e,currentId:t,menu:r,onNew:a}){const o=e.find(l=>l.id===t);return f.jsxs("nav",{id:"projects","aria-label":"Projects",children:[f.jsxs("div",{className:"nav-head",children:[f.jsx("span",{children:"Projects"}),f.jsx("button",{className:"nav-add",title:"New project","aria-label":"New project",onClick:a,children:"+"})]}),f.jsx("div",{className:"proj-row",children:f.jsxs(q$,{value:t||"",onValueChange:l=>{l&&l!==t&&(Yt("/"+l),hr())},children:[f.jsxs(Z$,{id:"project-select","aria-label":`Switch project — current: ${o?.name??"none"}`,title:o?.name,className:"proj-trigger",children:[o&&f.jsx("span",{className:"proj-mark","aria-hidden":"true",style:{background:vl(o.name)},children:f.jsx(Vs,{name:o.icon})}),o?f.jsx("span",{"data-slot":"select-value",children:o.name}):f.jsx(G$,{placeholder:"Select a project"})]}),f.jsx(K$,{className:"proj-menu",position:"popper",sideOffset:4,children:e.map(l=>f.jsxs(Y$,{value:l.id,children:[f.jsx("span",{className:"proj-mark","aria-hidden":"true",style:{background:vl(l.name)},children:f.jsx(Vs,{name:l.icon})}),l.name]},l.id))})]})}),r&&f.jsx("ul",{className:"nav-menu","aria-label":"Project pages",children:[["dashboard","Dashboard","dashboard",r.onDashboard],["install","Installation","terminal",r.onInstall],["history","History","hist",r.onHistory],["settings","Settings","gear",r.onSettings]].map(([l,u,d,m])=>f.jsx("li",{children:f.jsxs("div",{id:"nav-"+l,className:"row"+(r.active===l?" active":""),role:"button",tabIndex:0,onClick:m,onKeyDown:p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),m())},children:[f.jsx(nt,{name:d}),f.jsx("span",{className:"label",children:u})]})},l))})]})}function FC({...e}){return f.jsx(YM,{"data-slot":"dropdown-menu",...e})}function VC({...e}){return f.jsx(QM,{"data-slot":"dropdown-menu-trigger",...e})}function UC({className:e,sideOffset:t=4,...r}){return f.jsx(XM,{children:f.jsx(JM,{"data-slot":"dropdown-menu-content",sideOffset:t,className:We("z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",e),...r})})}function Is({className:e,inset:t,variant:r="default",...a}){return f.jsx(eN,{"data-slot":"dropdown-menu-item","data-inset":t,"data-variant":r,className:We("relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:text-destructive!",e),...a})}function im({className:e,inset:t,...r}){return f.jsx(WM,{"data-slot":"dropdown-menu-label","data-inset":t,className:We("px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",e),...r})}const J$="https://github.com/runbear-io/beardrive";function W$(){return f.jsx("svg",{viewBox:"0 0 16 16",className:"gh-mark",fill:"currentColor","aria-hidden":"true",children:f.jsx("path",{d:"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"})})}function eI({me:e,org:t,admin:r,orgActive:a,billing:o}){const l=e.name||e.email,[u,d]=S.useState(!1),m=t?Qs(t.manage_url):null,p=o?Qs(o.url):null;return f.jsxs("footer",{id:"accountbar",children:[f.jsxs("a",{className:"gh-star",href:J$,target:"_blank",rel:"noreferrer",children:[f.jsx(W$,{}),f.jsx("span",{children:"Star on GitHub"}),f.jsx("span",{className:"ext","aria-hidden":"true",children:"↗"}),f.jsx("span",{className:"sr-only",children:" (opens in a new tab)"})]}),f.jsxs(FC,{modal:!1,open:u,onOpenChange:d,children:[f.jsx(VC,{asChild:!0,children:f.jsxs("button",{id:"account-btn",className:a?"active":void 0,"aria-label":"Account menu",children:[f.jsx("span",{className:"avatar",style:{background:vl(e.email)},"aria-hidden":"true",children:(l.trim()[0]||"?").toUpperCase()}),f.jsxs("span",{className:"acct",children:[f.jsx("b",{children:l}),e.name&&f.jsx("small",{children:e.email})]}),f.jsx(nt,{name:"chev"})]})}),f.jsxs(UC,{id:"account-menu",side:"top",align:"start",sideOffset:6,className:"acct-menu",children:[t&&f.jsxs(f.Fragment,{children:[f.jsx(im,{className:"menu-sec",children:"Organization"}),f.jsx(Is,{asChild:!0,children:f.jsxs("a",{id:"menu-org-settings","aria-current":a?"page":void 0,...m,onClick:y=>{m?.onClick?.(y),d(!1)},children:[f.jsx(nt,{name:"gear"}),f.jsxs("span",{children:[f.jsx("b",{children:t.name})," Settings"]}),!t.manage_url.startsWith("/")&&f.jsxs(f.Fragment,{children:[f.jsx("span",{className:"ext","aria-hidden":"true",children:"↗"}),f.jsx("span",{className:"sr-only",children:" (opens in a new tab)"})]})]})}),o&&f.jsx(Is,{asChild:!0,children:f.jsxs("a",{id:"menu-billing",...p,onClick:y=>{p?.onClick?.(y),d(!1)},children:[f.jsx(nt,{name:"card"}),f.jsx("span",{children:"Billing"}),f.jsx("span",{className:"ps-chip plan-chip",children:o.plan})]})})]}),r&&f.jsxs(f.Fragment,{children:[f.jsx(im,{className:"menu-sec",children:"Hub"}),f.jsxs(Is,{id:"menu-hub-admin",onSelect:r.onClick,children:[f.jsx(nt,{name:"shield"}),f.jsxs("span",{children:["Signup & access",r.pending?` · ${r.pending}`:""]})]})]}),f.jsx(im,{className:"menu-sec",children:"Account"}),f.jsx(Is,{asChild:!0,children:f.jsxs("a",{id:"signout",href:"/auth/logout",children:[f.jsx(nt,{name:"power"}),f.jsx("span",{children:"Log out"})]})})]})]})]})}function Pi({className:e,...t}){return f.jsx("div",{"data-slot":"card",className:We("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",e),...t})}function Fi({className:e,...t}){return f.jsx("div",{"data-slot":"card-header",className:We("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",e),...t})}function Vi({className:e,...t}){return f.jsx("div",{"data-slot":"card-title",className:We("leading-none font-semibold",e),...t})}function qs({className:e,...t}){return f.jsx("div",{"data-slot":"card-description",className:We("text-muted-foreground text-sm",e),...t})}function Ui({className:e,...t}){return f.jsx("div",{"data-slot":"card-content",className:We("px-6",e),...t})}function ti({className:e,orientation:t="horizontal",decorative:r=!0,...a}){return f.jsx(MN,{"data-slot":"separator",decorative:r,orientation:t,className:We("bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",e),...a})}function tI({url:e}){const t=Ft({queryKey:["billing"],queryFn:()=>qt(e)});if(t.isLoading)return f.jsx("div",{className:"empty",children:"Loading…"});if(t.error||!t.data)return f.jsxs("div",{className:"empty",children:[f.jsx("h3",{children:"Billing is unavailable"}),f.jsx("p",{children:t.error?.message||"Try again shortly."})]});const r=t.data;return f.jsxs("div",{className:"project-settings",id:"billing-view",children:[f.jsxs("h2",{children:["Billing",f.jsx("span",{className:"ps-chip plan-chip",children:r.plan.name})]}),f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsxs(Vi,{children:[r.plan.name," plan",r.plan.status?` (${r.plan.status})`:""]}),f.jsxs(qs,{children:["Organization ",r.org," · ",r.usage.used," of ",r.usage.cap," used · ",r.seats.used," of ",r.seats.cap," ",r.seats.cap===1?"seat":"seats"]})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsx("div",{className:"usage-bar",children:f.jsx("div",{style:{width:`${r.usage.pct}%`}})})})]}),r.owner?f.jsx("div",{className:"plan-grid",children:r.plans.map(a=>f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:a.name}),f.jsx(qs,{children:a.blurb})]}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsxs("p",{className:"plan-price",children:[a.price,f.jsx("small",{children:" / user / month"})]}),f.jsxs("form",{method:"post",action:r.checkout_url,children:[f.jsx("input",{type:"hidden",name:"plan",value:a.id}),f.jsx(xt,{type:"submit",disabled:a.current,variant:a.current?"subtle":"default",children:a.current?"Current plan":`Upgrade to ${a.name}`})]})]})]},a.id))}):f.jsx("p",{className:"muted-note",children:"Only an organization owner can change the plan."}),r.owner&&r.has_customer&&f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"Manage subscription"}),f.jsx(qs,{children:"Change seats, update the card, download invoices, or cancel."})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsx("form",{method:"post",action:r.portal_url,children:f.jsx(xt,{type:"submit",variant:"subtle",children:"Open the billing portal"})})})]})]})}function hu({className:e,type:t,...r}){return f.jsx("input",{type:t,"data-slot":"input",className:We("h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30","focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50","aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",e),...r})}function am({className:e,...t}){return f.jsx(nN,{"data-slot":"label",className:We("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",e),...t})}function nI({className:e,...t}){return f.jsx("textarea",{"data-slot":"textarea",className:We("border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",e),...t})}const lw={read:1,write:2,admin:3};function _a(e,t){return(lw[e||""]||0)>=(lw[t]||0)}const Wm=280,rI=vg({name:fu().trim().min(1,"Give the project a name.").max(120,"Keep the name under 120 characters."),description:fu().max(Wm,`Keep the description under ${Wm} characters.`),icon:fu()});function iI({project:e,org:t,onDeleted:r}){const a=M_(),o=_a(e.perm,"admin"),l=lg({resolver:gg(rI),defaultValues:{name:e.name,description:e.description??"",icon:e.icon??""}});S.useEffect(()=>{l.reset({name:e.name,description:e.description??"",icon:e.icon??""})},[e.id,e.name,e.description,e.icon]);const u=l.watch("icon"),d=l.watch("description"),m=l.handleSubmit(async p=>{const y=l.formState.dirtyFields,v={};if(y.name&&(v.name=p.name.trim()),y.description&&(v.description=p.description),y.icon&&(v.icon=p.icon),Object.keys(v).length!==0)try{await Wn("PATCH","/api/projects/"+e.id,v),qe("Saved."),l.reset({...p,name:p.name.trim()}),await a()}catch(b){qe(b.message,!0)}});return f.jsxs("div",{className:"project-settings",children:[f.jsxs("h2",{children:[e.name,!_a(e.perm,"write")&&f.jsx("span",{className:"ps-chip",children:"Read-only"})]}),f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"General"}),f.jsx(qs,{children:"Name, description and icon for this project."})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsxs("form",{className:"ps-form",onSubmit:m,children:[f.jsxs("div",{className:"ps-field",children:[f.jsx(am,{htmlFor:"ps-icon-btn",children:"Icon"}),f.jsxs("div",{className:"ps-icon-row",children:[f.jsx("span",{className:"proj-mark","aria-hidden":"true",style:{background:vl(e.name)},children:f.jsx(Vs,{name:u})}),f.jsxs(FC,{children:[f.jsx(VC,{asChild:!0,children:f.jsx(xt,{id:"ps-icon-btn",type:"button",variant:"subtle",disabled:!o,children:"Change"})}),f.jsxs(UC,{align:"start",className:"ps-icon-grid",children:[f.jsx(Is,{className:"ps-icon-cell"+(u===""?" active":""),title:"Default","aria-label":"Default icon",onSelect:()=>l.setValue("icon","",{shouldDirty:!0}),children:f.jsx(Vs,{})}),Object.keys(Lm).map(p=>f.jsx(Is,{className:"ps-icon-cell"+(u===p?" active":""),title:p,"aria-label":p,onSelect:()=>l.setValue("icon",p,{shouldDirty:!0}),children:f.jsx(Vs,{name:p})},p))]})]})]})]}),f.jsxs("div",{className:"ps-field",children:[f.jsx(am,{htmlFor:"ps-name",children:"Name"}),f.jsx(hu,{id:"ps-name",disabled:!o,"aria-invalid":!!l.formState.errors.name,"aria-describedby":l.formState.errors.name?"ps-name-err":void 0,...l.register("name")}),l.formState.errors.name&&f.jsx("span",{id:"ps-name-err",role:"alert",className:"field-err",children:l.formState.errors.name.message})]}),f.jsxs("div",{className:"ps-field",children:[f.jsxs(am,{htmlFor:"ps-desc",children:["Description ",f.jsx("span",{className:"ps-opt",children:"(optional)"})]}),f.jsx(nI,{id:"ps-desc",rows:2,disabled:!o,placeholder:"What this project is for.","aria-invalid":!!l.formState.errors.description,"aria-describedby":l.formState.errors.description?"ps-desc-err":void 0,...l.register("description")}),f.jsxs("div",{className:"ps-meta",children:[l.formState.errors.description?f.jsx("span",{id:"ps-desc-err",role:"alert",className:"field-err",children:l.formState.errors.description.message}):f.jsx("span",{}),f.jsxs("span",{className:"ps-count",children:[d.length," / ",Wm]})]})]}),o&&f.jsxs(f.Fragment,{children:[f.jsx(ti,{}),f.jsx("div",{className:"ps-actions",children:f.jsx(xt,{id:"ps-save",type:"submit",variant:"primary",disabled:!l.formState.isDirty||l.formState.isSubmitting,children:"Save changes"})})]})]})})]}),f.jsx(aI,{project:e}),f.jsx(oI,{project:e,org:t}),f.jsxs(Pi,{children:[f.jsx(Fi,{children:f.jsx(Vi,{children:"About"})}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsxs("dl",{className:"ps-facts",children:[f.jsx("dt",{children:"Project id"}),f.jsx("dd",{children:f.jsx("code",{children:e.id})}),t&&f.jsxs(f.Fragment,{children:[f.jsx("dt",{children:"Workspace"}),f.jsx("dd",{children:t.name})]}),e.created&&f.jsxs(f.Fragment,{children:[f.jsx("dt",{children:"Created"}),f.jsx("dd",{children:new Date(e.created).toLocaleDateString()})]})]}),f.jsxs("p",{className:"ps-note ps-export",children:[f.jsx("strong",{children:"Take your files elsewhere."})," Run ",f.jsx("code",{children:"bdrive export"})," in the synced folder to write the whole project — every device's journal and every content blob, so full history and authorship — into a single archive. ",f.jsx("code",{children:"bdrive import"})," restores it into any other BearDrive hub, self-hosted or cloud. Export warns first if this device still has changes it hasn't pushed."," ",f.jsx("a",{href:"https://docs.beardrive.ai/reference/migration/",target:"_blank",rel:"noreferrer",children:"How migration works →"})]})]})]}),o&&f.jsxs(Pi,{className:"ps-danger",children:[f.jsx(Fi,{children:f.jsx(Vi,{children:"Danger zone"})}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsx("p",{children:"Deleting removes the project from this hub. Its files stay in storage. This can't be undone."}),f.jsx(xt,{variant:"danger",onClick:async()=>{if(await T_(`Delete “${e.name}”?`,"This can't be undone. Type the project name to confirm:","","Delete project",{match:e.name,danger:!0})!==null)try{await Wn("DELETE","/api/projects/"+e.id),qe(`Deleted “${e.name}”.`),await r()}catch(y){qe(y.message,!0)}},children:"Delete project"})]})]})]})}function aI({project:e}){const t=ka(),{data:r,error:a,isLoading:o}=O_(e.id);return a?null:f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"Public links"}),f.jsxs(qs,{children:["Files in this project that anyone with the URL can read — no account needed.",(r||[]).some(l=>l.opens!==void 0)&&f.jsxs(f.Fragment,{children:[" ",$C]})]})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsx(IC,{shares:r||[],loading:o,canRevoke:_a(e.perm,"write"),onChanged:()=>t.invalidateQueries({queryKey:["shares",e.id]}),empty:"No public links."})})]})}const ep=[{value:"admin",label:"Admin"},{value:"write",label:"Write"},{value:"read",label:"Read"},{value:"none",label:"No access"}],sI=Object.fromEntries(ep.map(e=>[e.value,e.label]));function oI({project:e,org:t}){const r=ka(),{data:a,error:o}=k3(e.id),l=_a(e.perm,"admin"),u=()=>{r.invalidateQueries({queryKey:["permissions",e.id]}),r.invalidateQueries({queryKey:["projects"]})},d=async(x,w)=>{try{await x(),qe(w)}catch(_){qe(_.message,!0)}u()};if(o||!a)return null;const m=a,p=`/api/p/${e.id}/permissions`,y=new Set((t?.members||[]).filter(x=>x.role==="owner").map(x=>x.email.toLowerCase())),v=[...m.grants.filter(x=>!y.has(x.email.toLowerCase())),...[...y].sort().map(x=>({email:x,level:"admin",owner:!0}))],b=async()=>{const x=await T_("Add an exception","Email of a workspace member. They get Read access; change it in the table.","","Add");x===null||!x.trim()||await d(()=>Wn("PUT",`${p}/${encodeURIComponent(x.trim())}`,{level:"read"}),"Added.")};return f.jsxs(Pi,{className:"ps-people",children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"People"}),f.jsx(qs,{children:"Who can see and change this project."})]}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsxs("p",{className:"ps-row",children:[f.jsxs("span",{children:["Everyone in ",t?.name||"this workspace"," can"]}),f.jsx("select",{"aria-label":"Default access for workspace members",disabled:!l,value:m.default,onChange:async x=>{const w=x.target.value;if(w==="none"&&!await zi("Make this project invite-only?","Only people listed below (and workspace owners) will see this project.","Make invite-only")){u();return}await d(()=>Wn("PUT",p,{default:w}),"Default access updated.")},children:ep.filter(x=>x.value!=="admin").map(x=>f.jsx("option",{value:x.value,children:x.label},x.value))})]}),m.default==="none"&&f.jsx("p",{className:"ps-note",children:"This project is invite-only: only the people below and workspace owners can see it."}),f.jsxs("div",{className:"ps-people-head",children:[f.jsx("h4",{children:"Exceptions"}),l&&f.jsx(xt,{type:"button",variant:"subtle",onClick:b,children:"+ Add"})]}),v.length===0?f.jsx("p",{className:"ps-note",children:"No exceptions — everyone gets the access above."}):f.jsx("div",{className:"admin-list",children:v.map(x=>{const w="owner"in x;return f.jsxs("div",{className:"admin-item",children:[f.jsxs("span",{className:"ai-main",title:x.email,children:[x.email,m.creator&&x.email.toLowerCase()===m.creator.toLowerCase()&&f.jsx("span",{className:"ai-tag",children:" (creator)"})]}),w?f.jsx("span",{className:"ai-tag",children:"Workspace owner — always admin"}):f.jsxs("span",{className:"role-cell",children:[f.jsx("select",{"aria-label":`Access for ${x.email}`,disabled:!l,value:x.level,onChange:_=>d(()=>Wn("PUT",`${p}/${encodeURIComponent(x.email)}`,{level:_.target.value}),`${x.email} is now ${sI[_.target.value]||_.target.value}.`),children:ep.map(_=>f.jsx("option",{value:_.value,children:_.label},_.value))}),l&&f.jsx("button",{className:"ai-del","aria-label":`Remove exception for ${x.email}`,onClick:()=>d(()=>Wn("DELETE",`${p}/${encodeURIComponent(x.email)}`),"Reverted to the default access."),children:"Remove"})]})]},x.email)})})]})]})}const HC="https://raw.githubusercontent.com/runbear-io/beardrive/main/INSTALL_FOR_AGENTS.md";function BC({project:e,existing:t}){const r=window.location.origin,a=t?'. I already have a folder of notes — ask me which one to sync (the project is named "':'. Ask me which folder to sync (the project is named "',o="Follow "+HC+` +Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(const u of e.seen.entries()){const d=u[1];if(t===u[0]){l(u);continue}if(e.external){const p=e.external.registry.get(u[0])?.id;if(t!==u[0]&&p){l(u);continue}}if(e.metadataRegistry.get(u[0])?.id){l(u);continue}if(d.cycle){l(u);continue}if(d.count>1&&e.reused==="ref"){l(u);continue}}}function EC(e,t){const r=e.seen.get(t);if(!r)throw new Error("Unprocessed schema. This is a bug in Zod.");const a=d=>{const m=e.seen.get(d);if(m.ref===null)return;const p=m.def??m.schema,y={...p},v=m.ref;if(m.ref=null,v){a(v);const x=e.seen.get(v),w=x.schema;if(w.$ref&&(e.target==="draft-07"||e.target==="draft-04"||e.target==="openapi-3.0")?(p.allOf=p.allOf??[],p.allOf.push(w)):Object.assign(p,w),Object.assign(p,y),d._zod.parent===v)for(const E in p)E==="$ref"||E==="allOf"||E in y||delete p[E];if(w.$ref&&x.def)for(const E in p)E==="$ref"||E==="allOf"||E in x.def&&JSON.stringify(p[E])===JSON.stringify(x.def[E])&&delete p[E]}const b=d._zod.parent;if(b&&b!==v){a(b);const x=e.seen.get(b);if(x?.schema.$ref&&(p.$ref=x.schema.$ref,x.def))for(const w in p)w==="$ref"||w==="allOf"||w in x.def&&JSON.stringify(p[w])===JSON.stringify(x.def[w])&&delete p[w]}e.override({zodSchema:d,jsonSchema:p,path:m.path??[]})};for(const d of[...e.seen.entries()].reverse())a(d[0]);const o={};if(e.target==="draft-2020-12"?o.$schema="https://json-schema.org/draft/2020-12/schema":e.target==="draft-07"?o.$schema="http://json-schema.org/draft-07/schema#":e.target==="draft-04"?o.$schema="http://json-schema.org/draft-04/schema#":e.target,e.external?.uri){const d=e.external.registry.get(t)?.id;if(!d)throw new Error("Schema is missing an `id` property");o.$id=e.external.uri(d)}Object.assign(o,r.def??r.schema);const l=e.metadataRegistry.get(t)?.id;l!==void 0&&o.id===l&&delete o.id;const u=e.external?.defs??{};for(const d of e.seen.entries()){const m=d[1];m.def&&m.defId&&(m.def.id===m.defId&&delete m.def.id,u[m.defId]=m.def)}e.external||Object.keys(u).length>0&&(e.target==="draft-2020-12"?o.$defs=u:o.definitions=u);try{const d=JSON.parse(JSON.stringify(o));return Object.defineProperty(d,"~standard",{value:{...t["~standard"],jsonSchema:{input:Ou(t,"input",e.processors),output:Ou(t,"output",e.processors)}},enumerable:!1,writable:!1}),d}catch{throw new Error("Error converting schema to JSON.")}}function gn(e,t){const r=t??{seen:new Set};if(r.seen.has(e))return!1;r.seen.add(e);const a=e._zod.def;if(a.type==="transform")return!0;if(a.type==="array")return gn(a.element,r);if(a.type==="set")return gn(a.valueType,r);if(a.type==="lazy")return gn(a.getter(),r);if(a.type==="promise"||a.type==="optional"||a.type==="nonoptional"||a.type==="nullable"||a.type==="readonly"||a.type==="default"||a.type==="prefault")return gn(a.innerType,r);if(a.type==="intersection")return gn(a.left,r)||gn(a.right,r);if(a.type==="record"||a.type==="map")return gn(a.keyType,r)||gn(a.valueType,r);if(a.type==="pipe")return e._zod.traits.has("$ZodCodec")?!0:gn(a.in,r)||gn(a.out,r);if(a.type==="object"){for(const o in a.shape)if(gn(a.shape[o],r))return!0;return!1}if(a.type==="union"){for(const o of a.options)if(gn(o,r))return!0;return!1}if(a.type==="tuple"){for(const o of a.items)if(gn(o,r))return!0;return!!(a.rest&&gn(a.rest,r))}return!1}const BL=(e,t={})=>r=>{const a=_C({...r,processors:t});return cn(e,a),CC(a,e),EC(a,e)},Ou=(e,t,r={})=>a=>{const{libraryOptions:o,target:l}=a??{},u=_C({...o??{},target:l,io:t,processors:r});return cn(e,u),CC(u,e),EC(u,e)},qL={guid:"uuid",url:"uri",datetime:"date-time",json_string:"json-string",regex:""},GL=(e,t,r,a)=>{const o=r;o.type="string";const{minimum:l,maximum:u,format:d,patterns:m,contentEncoding:p}=e._zod.bag;if(typeof l=="number"&&(o.minLength=l),typeof u=="number"&&(o.maxLength=u),d&&(o.format=qL[d]??d,o.format===""&&delete o.format,d==="time"&&delete o.format),p&&(o.contentEncoding=p),m&&m.size>0){const y=[...m];y.length===1?o.pattern=y[0].source:y.length>1&&(o.allOf=[...y.map(v=>({...t.target==="draft-07"||t.target==="draft-04"||t.target==="openapi-3.0"?{type:"string"}:{},pattern:v.source}))])}},ZL=(e,t,r,a)=>{r.type="boolean"},KL=(e,t,r,a)=>{r.not={}},YL=(e,t,r,a)=>{},QL=(e,t,r,a)=>{const o=e._zod.def,l=cC(o.entries);l.every(u=>typeof u=="number")&&(r.type="number"),l.every(u=>typeof u=="string")&&(r.type="string"),r.enum=l},XL=(e,t,r,a)=>{if(t.unrepresentable==="throw")throw new Error("Custom types cannot be represented in JSON Schema")},JL=(e,t,r,a)=>{if(t.unrepresentable==="throw")throw new Error("Transforms cannot be represented in JSON Schema")},WL=(e,t,r,a)=>{const o=r,l=e._zod.def,{minimum:u,maximum:d}=e._zod.bag;typeof u=="number"&&(o.minItems=u),typeof d=="number"&&(o.maxItems=d),o.type="array",o.items=cn(l.element,t,{...a,path:[...a.path,"items"]})},e8=(e,t,r,a)=>{const o=r,l=e._zod.def;o.type="object",o.properties={};const u=l.shape;for(const p in u)o.properties[p]=cn(u[p],t,{...a,path:[...a.path,"properties",p]});const d=new Set(Object.keys(u)),m=new Set([...d].filter(p=>{const y=l.shape[p]._zod;return t.io==="input"?y.optin===void 0:y.optout===void 0}));m.size>0&&(o.required=Array.from(m)),l.catchall?._zod.def.type==="never"?o.additionalProperties=!1:l.catchall?l.catchall&&(o.additionalProperties=cn(l.catchall,t,{...a,path:[...a.path,"additionalProperties"]})):t.io==="output"&&(o.additionalProperties=!1)},t8=(e,t,r,a)=>{const o=e._zod.def,l=o.inclusive===!1,u=o.options.map((d,m)=>cn(d,t,{...a,path:[...a.path,l?"oneOf":"anyOf",m]}));l?r.oneOf=u:r.anyOf=u},n8=(e,t,r,a)=>{const o=e._zod.def,l=cn(o.left,t,{...a,path:[...a.path,"allOf",0]}),u=cn(o.right,t,{...a,path:[...a.path,"allOf",1]}),d=p=>"allOf"in p&&Object.keys(p).length===1,m=[...d(l)?l.allOf:[l],...d(u)?u.allOf:[u]];r.allOf=m},r8=(e,t,r,a)=>{const o=e._zod.def,l=cn(o.innerType,t,a),u=t.seen.get(e);t.target==="openapi-3.0"?(u.ref=o.innerType,r.nullable=!0):r.anyOf=[l,{type:"null"}]},i8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType},a8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType,r.default=JSON.parse(JSON.stringify(o.defaultValue))},s8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType,t.io==="input"&&(r._prefault=JSON.parse(JSON.stringify(o.defaultValue)))},o8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType;let u;try{u=o.catchValue(void 0)}catch{throw new Error("Dynamic catch values are not supported in JSON Schema")}r.default=u},l8=(e,t,r,a)=>{const o=e._zod.def,l=o.in._zod.traits.has("$ZodTransform"),u=t.io==="input"?l?o.out:o.in:o.out;cn(u,t,a);const d=t.seen.get(e);d.ref=u},c8=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType,r.readOnly=!0},RC=(e,t,r,a)=>{const o=e._zod.def;cn(o.innerType,t,a);const l=t.seen.get(e);l.ref=o.innerType};function Xm(){return Xm=Object.assign?Object.assign.bind():function(e){for(var t=1;t0){var m=o.errors[0][0];r[d]={message:m.message,type:m.code}}else r[d]={message:u,type:l};if(o.code==="invalid_union"&&o.errors.forEach(function(v){return v.forEach(function(b){return e.push(Xm({},b,{path:[].concat(o.path,b.path)}))})}),t){var p=r[d].types,y=p&&p[o.code];r[d]=og(d,t,r,l,y?[].concat(y,o.message):o.message)}e.shift()};e.length;)a();return r}function gg(e,t,r){if(r===void 0&&(r={}),(function(a){return"_def"in a&&typeof a._def=="object"&&"typeName"in a._def})(e))return function(a,o,l){try{return Promise.resolve(Qx(function(){return Promise.resolve(e[r.mode==="sync"?"parse":"parseAsync"](a,t)).then(function(u){return l.shouldUseNativeValidation&&Km({},l),{errors:{},values:r.raw?Object.assign({},a):u}})},function(u){if((function(d){return Array.isArray(d?.issues)})(u))return{values:{},errors:kx(u8(u.errors,!l.shouldUseNativeValidation&&l.criteriaMode==="all"),l)};throw u}))}catch(u){return Promise.reject(u)}};if((function(a){return"_zod"in a&&typeof a._zod=="object"})(e))return function(a,o,l){try{return Promise.resolve(Qx(function(){return Promise.resolve((r.mode==="sync"?h5:m5)(e,a,t)).then(function(u){return l.shouldUseNativeValidation&&Km({},l),{errors:{},values:r.raw?Object.assign({},a):u}})},function(u){if((function(d){return d instanceof mg})(u))return{values:{},errors:kx(d8(u.issues,!l.shouldUseNativeValidation&&l.criteriaMode==="all"),l)};throw u}))}catch(u){return Promise.reject(u)}};throw new Error("Invalid input: not a Zod schema")}const f8=me("ZodISODateTime",(e,t)=>{b6.init(e,t),Et.init(e,t)});function h8(e){return SL(f8,e)}const m8=me("ZodISODate",(e,t)=>{x6.init(e,t),Et.init(e,t)});function p8(e){return _L(m8,e)}const g8=me("ZodISOTime",(e,t)=>{w6.init(e,t),Et.init(e,t)});function v8(e){return CL(g8,e)}const y8=me("ZodISODuration",(e,t)=>{S6.init(e,t),Et.init(e,t)});function b8(e){return EL(y8,e)}const x8=(e,t)=>{mg.init(e,t),e.name="ZodError",Object.defineProperties(e,{format:{value:r=>f5(e,r)},flatten:{value:r=>d5(e,r)},addIssue:{value:r=>{e.issues.push(r),e.message=JSON.stringify(e.issues,Ym,2)}},addIssues:{value:r=>{e.issues.push(...r),e.message=JSON.stringify(e.issues,Ym,2)}},isEmpty:{get(){return e.issues.length===0}}})},nr=me("ZodError",x8,{Parent:Error}),w8=od(nr),S8=ld(nr),_8=cd(nr),C8=ud(nr),E8=v5(nr),R8=y5(nr),j8=b5(nr),T8=x5(nr),O8=w5(nr),A8=S5(nr),M8=_5(nr),N8=C5(nr),Xx=new WeakMap;function fd(e,t,r){const a=Object.getPrototypeOf(e);let o=Xx.get(a);if(o||(o=new Set,Xx.set(a,o)),!o.has(t)){o.add(t);for(const l in r){const u=r[l];Object.defineProperty(a,l,{configurable:!0,enumerable:!1,get(){const d=u.bind(this);return Object.defineProperty(this,l,{configurable:!0,writable:!0,enumerable:!0,value:d}),d},set(d){Object.defineProperty(this,l,{configurable:!0,writable:!0,enumerable:!0,value:d})}})}}}const Ut=me("ZodType",(e,t)=>(Vt.init(e,t),Object.assign(e["~standard"],{jsonSchema:{input:Ou(e,"input"),output:Ou(e,"output")}}),e.toJSONSchema=BL(e,{}),e.def=t,e.type=t.type,Object.defineProperty(e,"_def",{value:t}),e.parse=(r,a)=>w8(e,r,a,{callee:e.parse}),e.safeParse=(r,a)=>_8(e,r,a),e.parseAsync=async(r,a)=>S8(e,r,a,{callee:e.parseAsync}),e.safeParseAsync=async(r,a)=>C8(e,r,a),e.spa=e.safeParseAsync,e.encode=(r,a)=>E8(e,r,a),e.decode=(r,a)=>R8(e,r,a),e.encodeAsync=async(r,a)=>j8(e,r,a),e.decodeAsync=async(r,a)=>T8(e,r,a),e.safeEncode=(r,a)=>O8(e,r,a),e.safeDecode=(r,a)=>A8(e,r,a),e.safeEncodeAsync=async(r,a)=>M8(e,r,a),e.safeDecodeAsync=async(r,a)=>N8(e,r,a),fd(e,"ZodType",{check(...r){const a=this.def;return this.clone(Wi(a,{checks:[...a.checks??[],...r.map(o=>typeof o=="function"?{_zod:{check:o,def:{check:"custom"},onattach:[]}}:o)]}),{parent:!0})},with(...r){return this.check(...r)},clone(r,a){return ea(this,r,a)},brand(){return this},register(r,a){return r.add(this,a),this},refine(r,a){return this.check(E$(r,a))},superRefine(r,a){return this.check(R$(r,a))},overwrite(r){return this.check(eo(r))},optional(){return tw(this)},exactOptional(){return f$(this)},nullable(){return nw(this)},nullish(){return tw(nw(this))},nonoptional(r){return y$(this,r)},array(){return n$(this)},or(r){return a$([this,r])},and(r){return o$(this,r)},transform(r){return rw(this,u$(r))},default(r){return p$(this,r)},prefault(r){return v$(this,r)},catch(r){return x$(this,r)},pipe(r){return rw(this,r)},readonly(){return _$(this)},describe(r){const a=this.clone();return tl.add(a,{description:r}),a},meta(...r){if(r.length===0)return tl.get(this);const a=this.clone();return tl.add(a,r[0]),a},isOptional(){return this.safeParse(void 0).success},isNullable(){return this.safeParse(null).success},apply(r){return r(this)}}),Object.defineProperty(e,"description",{get(){return tl.get(e)?.description},configurable:!0}),e)),jC=me("_ZodString",(e,t)=>{pg.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(a,o,l)=>GL(e,a,o);const r=e._zod.bag;e.format=r.format??null,e.minLength=r.minimum??null,e.maxLength=r.maximum??null,fd(e,"_ZodString",{regex(...a){return this.check(OL(...a))},includes(...a){return this.check(NL(...a))},startsWith(...a){return this.check(DL(...a))},endsWith(...a){return this.check(kL(...a))},min(...a){return this.check(Tu(...a))},max(...a){return this.check(wC(...a))},length(...a){return this.check(SC(...a))},nonempty(...a){return this.check(Tu(1,...a))},lowercase(a){return this.check(AL(a))},uppercase(a){return this.check(ML(a))},trim(){return this.check(LL())},normalize(...a){return this.check(zL(...a))},toLowerCase(){return this.check($L())},toUpperCase(){return this.check(IL())},slugify(){return this.check(PL())}})}),D8=me("ZodString",(e,t)=>{pg.init(e,t),jC.init(e,t),e.email=r=>e.check(tL(k8,r)),e.url=r=>e.check(sL(z8,r)),e.jwt=r=>e.check(wL(Q8,r)),e.emoji=r=>e.check(oL(L8,r)),e.guid=r=>e.check(Yx(Jx,r)),e.uuid=r=>e.check(nL(au,r)),e.uuidv4=r=>e.check(rL(au,r)),e.uuidv6=r=>e.check(iL(au,r)),e.uuidv7=r=>e.check(aL(au,r)),e.nanoid=r=>e.check(lL($8,r)),e.guid=r=>e.check(Yx(Jx,r)),e.cuid=r=>e.check(cL(I8,r)),e.cuid2=r=>e.check(uL(P8,r)),e.ulid=r=>e.check(dL(F8,r)),e.base64=r=>e.check(yL(Z8,r)),e.base64url=r=>e.check(bL(K8,r)),e.xid=r=>e.check(fL(V8,r)),e.ksuid=r=>e.check(hL(U8,r)),e.ipv4=r=>e.check(mL(H8,r)),e.ipv6=r=>e.check(pL(B8,r)),e.cidrv4=r=>e.check(gL(q8,r)),e.cidrv6=r=>e.check(vL(G8,r)),e.e164=r=>e.check(xL(Y8,r)),e.datetime=r=>e.check(h8(r)),e.date=r=>e.check(p8(r)),e.time=r=>e.check(v8(r)),e.duration=r=>e.check(b8(r))});function fu(e){return eL(D8,e)}const Et=me("ZodStringFormat",(e,t)=>{St.init(e,t),jC.init(e,t)}),k8=me("ZodEmail",(e,t)=>{u6.init(e,t),Et.init(e,t)}),Jx=me("ZodGUID",(e,t)=>{l6.init(e,t),Et.init(e,t)}),au=me("ZodUUID",(e,t)=>{c6.init(e,t),Et.init(e,t)}),z8=me("ZodURL",(e,t)=>{d6.init(e,t),Et.init(e,t)}),L8=me("ZodEmoji",(e,t)=>{f6.init(e,t),Et.init(e,t)}),$8=me("ZodNanoID",(e,t)=>{h6.init(e,t),Et.init(e,t)}),I8=me("ZodCUID",(e,t)=>{m6.init(e,t),Et.init(e,t)}),P8=me("ZodCUID2",(e,t)=>{p6.init(e,t),Et.init(e,t)}),F8=me("ZodULID",(e,t)=>{g6.init(e,t),Et.init(e,t)}),V8=me("ZodXID",(e,t)=>{v6.init(e,t),Et.init(e,t)}),U8=me("ZodKSUID",(e,t)=>{y6.init(e,t),Et.init(e,t)}),H8=me("ZodIPv4",(e,t)=>{_6.init(e,t),Et.init(e,t)}),B8=me("ZodIPv6",(e,t)=>{C6.init(e,t),Et.init(e,t)}),q8=me("ZodCIDRv4",(e,t)=>{E6.init(e,t),Et.init(e,t)}),G8=me("ZodCIDRv6",(e,t)=>{R6.init(e,t),Et.init(e,t)}),Z8=me("ZodBase64",(e,t)=>{j6.init(e,t),Et.init(e,t)}),K8=me("ZodBase64URL",(e,t)=>{O6.init(e,t),Et.init(e,t)}),Y8=me("ZodE164",(e,t)=>{A6.init(e,t),Et.init(e,t)}),Q8=me("ZodJWT",(e,t)=>{N6.init(e,t),Et.init(e,t)}),X8=me("ZodBoolean",(e,t)=>{D6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>ZL(e,r,a)});function Wx(e){return RL(X8,e)}const J8=me("ZodUnknown",(e,t)=>{k6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>YL()});function ew(){return jL(J8)}const W8=me("ZodNever",(e,t)=>{z6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>KL(e,r,a)});function e$(e){return TL(W8,e)}const t$=me("ZodArray",(e,t)=>{L6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>WL(e,r,a,o),e.element=t.element,fd(e,"ZodArray",{min(r,a){return this.check(Tu(r,a))},nonempty(r){return this.check(Tu(1,r))},max(r,a){return this.check(wC(r,a))},length(r,a){return this.check(SC(r,a))},unwrap(){return this.element}})});function n$(e,t){return FL(t$,e,t)}const r$=me("ZodObject",(e,t)=>{I6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>e8(e,r,a,o),pt(e,"shape",()=>t.shape),fd(e,"ZodObject",{keyof(){return l$(Object.keys(this._zod.def.shape))},catchall(r){return this.clone({...this._zod.def,catchall:r})},passthrough(){return this.clone({...this._zod.def,catchall:ew()})},loose(){return this.clone({...this._zod.def,catchall:ew()})},strict(){return this.clone({...this._zod.def,catchall:e$()})},strip(){return this.clone({...this._zod.def,catchall:void 0})},extend(r){return a5(this,r)},safeExtend(r){return s5(this,r)},merge(r){return o5(this,r)},pick(r){return r5(this,r)},omit(r){return i5(this,r)},partial(...r){return l5(TC,this,r[0])},required(...r){return c5(OC,this,r[0])}})});function vg(e,t){const r={type:"object",shape:e??{},...Ie(t)};return new r$(r)}const i$=me("ZodUnion",(e,t)=>{P6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>t8(e,r,a,o),e.options=t.options});function a$(e,t){return new i$({type:"union",options:e,...Ie(t)})}const s$=me("ZodIntersection",(e,t)=>{F6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>n8(e,r,a,o)});function o$(e,t){return new s$({type:"intersection",left:e,right:t})}const Jm=me("ZodEnum",(e,t)=>{V6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(a,o,l)=>QL(e,a,o),e.enum=t.entries,e.options=Object.values(t.entries);const r=new Set(Object.keys(t.entries));e.extract=(a,o)=>{const l={};for(const u of a)if(r.has(u))l[u]=t.entries[u];else throw new Error(`Key ${u} not found in enum`);return new Jm({...t,checks:[],...Ie(o),entries:l})},e.exclude=(a,o)=>{const l={...t.entries};for(const u of a)if(r.has(u))delete l[u];else throw new Error(`Key ${u} not found in enum`);return new Jm({...t,checks:[],...Ie(o),entries:l})}});function l$(e,t){const r=Array.isArray(e)?Object.fromEntries(e.map(a=>[a,a])):e;return new Jm({type:"enum",entries:r,...Ie(t)})}const c$=me("ZodTransform",(e,t)=>{U6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>JL(e,r),e._zod.parse=(r,a)=>{if(a.direction==="backward")throw new lC(e.constructor.name);r.addIssue=l=>{if(typeof l=="string")r.issues.push(gl(l,r.value,t));else{const u=l;u.fatal&&(u.continue=!1),u.code??(u.code="custom"),u.input??(u.input=r.value),u.inst??(u.inst=e),r.issues.push(gl(u))}};const o=t.transform(r.value,r);return o instanceof Promise?o.then(l=>(r.value=l,r.fallback=!0,r)):(r.value=o,r.fallback=!0,r)}});function u$(e){return new c$({type:"transform",transform:e})}const TC=me("ZodOptional",(e,t)=>{xC.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>RC(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function tw(e){return new TC({type:"optional",innerType:e})}const d$=me("ZodExactOptional",(e,t)=>{H6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>RC(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function f$(e){return new d$({type:"optional",innerType:e})}const h$=me("ZodNullable",(e,t)=>{B6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>r8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function nw(e){return new h$({type:"nullable",innerType:e})}const m$=me("ZodDefault",(e,t)=>{q6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>a8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType,e.removeDefault=e.unwrap});function p$(e,t){return new m$({type:"default",innerType:e,get defaultValue(){return typeof t=="function"?t():dC(t)}})}const g$=me("ZodPrefault",(e,t)=>{G6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>s8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function v$(e,t){return new g$({type:"prefault",innerType:e,get defaultValue(){return typeof t=="function"?t():dC(t)}})}const OC=me("ZodNonOptional",(e,t)=>{Z6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>i8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function y$(e,t){return new OC({type:"nonoptional",innerType:e,...Ie(t)})}const b$=me("ZodCatch",(e,t)=>{K6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>o8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType,e.removeCatch=e.unwrap});function x$(e,t){return new b$({type:"catch",innerType:e,catchValue:typeof t=="function"?t:()=>t})}const w$=me("ZodPipe",(e,t)=>{Y6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>l8(e,r,a,o),e.in=t.in,e.out=t.out});function rw(e,t){return new w$({type:"pipe",in:e,out:t})}const S$=me("ZodReadonly",(e,t)=>{Q6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>c8(e,r,a,o),e.unwrap=()=>e._zod.def.innerType});function _$(e){return new S$({type:"readonly",innerType:e})}const C$=me("ZodCustom",(e,t)=>{X6.init(e,t),Ut.init(e,t),e._zod.processJSONSchema=(r,a,o)=>XL(e,r)});function E$(e,t={}){return VL(C$,e,t)}function R$(e,t){return UL(e,t)}const j$=/\.(md|markdown)$/i,T$=/\.(png|jpe?g|gif|svg|webp|ico|bmp|avif)$/i,AC=/\.html?$/i,MC=/\.pdf$/i,O$=/\.(csv|tsv)$/i,A$=/\.(txt|log|json|ya?ml|toml|csv|go|py|js|ts|jsx|tsx|sh|bash|zsh|rb|rs|c|h|cpp|java|kt|swift|sql|css|xml|ini|conf|env|mod|sum|jsonl)$/i;function yg(e){if(e<1024)return e+" B";const t=["KB","MB","GB","TB"];let r=-1;do e/=1024,r++;while(e>=1024&&ra.path.toLowerCase()===r||a.path.toLowerCase()===r+".md")||t.find(a=>{const o=a.name.toLowerCase();return o===r||o===r+".md"})}async function Na(e){try{if(navigator.clipboard)return await navigator.clipboard.writeText(e),!0}catch{}return!1}const DC="bdrive.lastProject";function N$(){try{return localStorage.getItem(DC)||""}catch{return""}}function D$(e){try{localStorage.setItem(DC,e)}catch{}}function hd(e){return e.user_name?`${e.user_name} <${e.user}>`:e.user||e.author||"unknown"}function k$({className:e,...t}){return f.jsx("div",{"data-slot":"table-container",className:"relative w-full overflow-x-auto",children:f.jsx("table",{"data-slot":"table",className:We("w-full caption-bottom text-sm",e),...t})})}function z$({className:e,...t}){return f.jsx("thead",{"data-slot":"table-header",className:We("[&_tr]:border-b",e),...t})}function L$({className:e,...t}){return f.jsx("tbody",{"data-slot":"table-body",className:We("[&_tr:last-child]:border-0",e),...t})}function iw({className:e,...t}){return f.jsx("tr",{"data-slot":"table-row",className:We("border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",e),...t})}function aw({className:e,...t}){return f.jsx("th",{"data-slot":"table-head",className:We("h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...t})}function $$({className:e,...t}){return f.jsx("td",{"data-slot":"table-cell",className:We("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",e),...t})}function I$({header:e}){const t=e.column.getIsSorted();return e.column.getCanSort()?f.jsx(aw,{"data-sort":t||void 0,"aria-sort":t==="asc"?"ascending":t==="desc"?"descending":"none",children:f.jsxs("button",{type:"button",className:"th-sort",onClick:e.column.getToggleSortingHandler(),children:[Bm(e.column.columnDef.header,e.getContext()),t==="asc"?" ↑":t==="desc"?" ↓":""]})}):f.jsx(aw,{children:Bm(e.column.columnDef.header,e.getContext())})}function kC({table:e,className:t}){return f.jsx("div",{className:"admin-list admin-card-table"+(t?" "+t:""),children:f.jsxs(k$,{className:"admin-table",children:[f.jsx(z$,{children:e.getHeaderGroups().map(r=>f.jsx(iw,{children:r.headers.map(a=>f.jsx(I$,{header:a},a.id))},r.id))}),f.jsx(L$,{children:e.getRowModel().rows.map(r=>f.jsx(iw,{className:"admin-item",children:r.getVisibleCells().map(a=>f.jsx($$,{children:Bm(a.column.columnDef.cell,a.getContext())},a.id))},r.id))})]})})}function zC(e){return e?"expires "+new Date(e).toLocaleDateString():"no expiry"}function P$(e){if(e.opens===void 0)return null;if(e.opens===0)return"not opened yet";const t=`${e.opens} open${e.opens===1?"":"s"}`;return e.last_opened?`${t} · last opened ${new Date(e.last_opened).toLocaleDateString()}`:t}function LC(e,t){const r=[];t&&e.project_name&&r.push(e.project_name),e.creator&&r.push("by "+e.creator),e.created&&r.push(new Date(e.created).toLocaleDateString()),r.push(zC(e.expires));const a=P$(e);return a&&r.push(a),r.join(" · ")}const $C="Opens count how many times a file has been read through a public link. Repeat opens from the same browser and network within 10 minutes count once — two people on one network using the same browser still count as one.";function IC({shares:e,onChanged:t,showProject:r=!1,canRevoke:a=!0,empty:o="No public shares.",loading:l=!1}){const[u,d]=S.useState([]),m=S.useMemo(()=>L_(),[]),p=S.useMemo(()=>[m.accessor("path",{header:"Path",cell:v=>f.jsx("a",{className:"ai-main mono",title:v.getValue(),...Qs(Oa(v.getValue(),v.row.original.project)),children:v.getValue()})}),m.accessor(v=>LC(v,r),{id:"detail",header:r?"Project":"Shared",cell:v=>f.jsx("span",{className:"ai-tag",children:v.getValue()})}),m.display({id:"actions",header:"",cell:v=>f.jsxs("span",{className:"share-acts",children:[f.jsx("button",{className:"ai-btn","aria-label":`Copy the public link to ${v.row.original.path}`,title:"Copy link",onClick:()=>Na(v.row.original.url).then(b=>qe(b?"Copied.":"Select and copy the link.")),children:f.jsx(nt,{name:"copy"})}),a&&f.jsx("button",{className:"ai-del","aria-label":`Revoke the share of ${v.row.original.path}`,onClick:()=>PC(v.row.original,t),children:"Revoke"})]})})],[m,t,r,a]),y=K_({data:e,columns:p,state:{sorting:u},onSortingChange:d,getCoreRowModel:G_(),getSortedRowModel:Z_()});return l?f.jsx("div",{className:"admin-list",children:f.jsx("div",{className:"admin-empty",children:"Loading…"})}):e.length===0?f.jsx("div",{className:"admin-list",children:f.jsx("div",{className:"admin-empty",children:o})}):f.jsx(kC,{table:y,className:"shares-table"})}async function PC(e,t){if(await zi("Revoke share link",`Revoke the public link to “${e.path}”? Anyone with the URL will lose access.`,"Revoke",!0))try{await Wn("DELETE","/api/shares/"+e.token),qe("Share revoked."),t()}catch(r){qe(r.message,!0)}}const F$=vg({name:fu().trim().min(1,"Give the organization a name.").max(60,"Keep it under 60 characters.")});function V$({org:e,projects:t,myEmail:r}){const a=ka(),o=e.role==="owner",l=()=>a.invalidateQueries({queryKey:["orgs"]}),u=()=>a.invalidateQueries({queryKey:["invites",e.id]}),d=()=>a.invalidateQueries({queryKey:["orgShares",e.id]}),m=lg({resolver:gg(F$),values:{name:e.name}}),{data:p}=Ft({queryKey:["invites",e.id],queryFn:()=>qt(`/api/orgs/${e.id}/invites`),enabled:o,select:x=>x.invites||[]}),{data:y,isLoading:v}=Ft({queryKey:["orgShares",e.id],queryFn:()=>qt(`/api/orgs/${e.id}/shares`),enabled:o,select:x=>x.shares||[]}),b=t.filter(x=>x.org===e.id);return f.jsxs("div",{className:"admin",children:[f.jsx("h1",{id:"org-title",children:e.name}),!o&&f.jsx("p",{className:"role-chip-row",children:f.jsx("span",{className:"ai-tag role-chip",children:"Member"})}),!o&&f.jsx("p",{className:"admin-sub",children:"Only owners can rename this organization, manage members, or issue invite links."}),o&&f.jsxs("form",{className:"admin-row",onSubmit:m.handleSubmit(async({name:x})=>{try{await Wn("PATCH","/api/orgs/"+e.id,{name:x}),qe("Renamed."),l()}catch(w){qe(w.message,!0)}}),children:[f.jsx("label",{className:"admin-lbl",htmlFor:"org-rename",children:"Organization name"}),f.jsx("input",{id:"org-rename",type:"text","aria-invalid":!!m.formState.errors.name,"aria-describedby":m.formState.errors.name?"org-rename-err":void 0,...m.register("name")}),f.jsx(xt,{variant:"subtle",id:"org-rename-btn",type:"submit",disabled:!m.formState.isDirty,children:"Rename org"}),m.formState.errors.name&&f.jsx("span",{id:"org-rename-err",role:"alert",className:"field-err",children:m.formState.errors.name.message})]}),f.jsx("h3",{children:"Members"}),f.jsx(U$,{org:e,owner:o,myEmail:r,onChanged:l}),f.jsx("h3",{children:"Projects"}),f.jsxs("div",{className:"admin-list",children:[b.length===0&&f.jsx("div",{className:"admin-empty",children:"No projects yet."}),b.map(x=>f.jsx("div",{className:"admin-item",children:f.jsx("span",{className:"ai-main",title:x.name,children:x.name})},x.id))]}),o&&f.jsxs(f.Fragment,{children:[f.jsxs("div",{className:"admin-h",children:[f.jsx("h3",{children:"Invite links"}),f.jsx(xt,{variant:"primary",onClick:async()=>{try{const x=await ei(`/api/orgs/${e.id}/invites`),w=await Na(x.url);qe(w?"Invite link copied to clipboard.":"Invite created — copy it from the list below."),u()}catch(x){qe(x.message,!0)}},children:"New invite"})]}),f.jsxs("div",{className:"admin-list",children:[p&&p.length===0&&f.jsx("div",{className:"admin-empty",children:"No active invite links."}),(p||[]).map(x=>f.jsxs("div",{className:"admin-item",children:[f.jsx("button",{type:"button",className:"ai-main mono ai-copy","aria-label":`Copy invite link ${x.url}`,title:x.url,onClick:()=>Na(x.url).then(w=>qe(w?"Copied.":"Select and copy the link.")),children:x.url}),f.jsx("span",{className:"ai-tag",children:(x.creator?"by "+x.creator+" · ":"")+(x.uses?x.uses+" joined · ":"unused · ")+"expires "+new Date(x.expires).toLocaleDateString()}),f.jsx("button",{className:"ai-del","aria-label":`Revoke invite ${x.token.slice(0,8)}`,onClick:async()=>{if(await zi("Revoke invite",`Revoke the link starting ${x.token.slice(0,8)}…? Anyone still holding it won't be able to join.`,"Revoke",!0))try{await Wn("DELETE",`/api/orgs/${e.id}/invites/${x.token}`),qe("Revoked."),u()}catch(w){qe(w.message,!0)}},children:"Revoke"})]},x.token))]}),f.jsx("h3",{children:"Public share links"}),f.jsx("p",{className:"admin-sub",children:"Every live link across this organization's projects. A project's own links are on its Settings page, and on the file itself."}),f.jsx(IC,{shares:y||[],loading:v,onChanged:d,showProject:!0})]})]})}function U$({org:e,owner:t,myEmail:r,onChanged:a}){const[o,l]=S.useState([{id:"email",desc:!1}]),u=S.useMemo(()=>L_(),[]),d=S.useMemo(()=>[u.accessor("email",{id:"email",header:"Member",cell:p=>{const y=!!r&&p.getValue().toLowerCase()===r.toLowerCase();return f.jsx("span",{className:"ai-main",title:p.getValue(),children:p.getValue()+(y?" (you)":"")})}}),u.accessor("role",{id:"role",header:"Role",cell:p=>{const y=p.row.original,v=!!r&&y.email.toLowerCase()===r.toLowerCase();return!t||v?f.jsx("span",{className:"ai-tag role-static",children:y.role}):f.jsxs("span",{className:"role-cell",children:[f.jsxs("select",{"aria-label":`Role for ${y.email}`,value:y.role,onChange:async b=>{try{await Wn("PATCH",`/api/orgs/${e.id}/members/${encodeURIComponent(y.email)}`,{role:b.target.value}),qe("Role updated.")}catch(x){qe(x.message,!0)}a()},children:[f.jsx("option",{value:"owner",children:"owner"}),f.jsx("option",{value:"member",children:"member"})]}),f.jsx("button",{className:"ai-del","aria-label":`Remove ${y.email}`,onClick:async()=>{if(await zi("Remove member",`Remove ${y.email} from ${e.name}?`,"Remove",!0))try{await Wn("DELETE",`/api/orgs/${e.id}/members/${encodeURIComponent(y.email)}`),qe("Removed."),a()}catch(b){qe(b.message,!0)}},children:"Remove"})]})}})],[u,e.id,e.name,t,r]),m=K_({data:e.members,columns:d,state:{sorting:o},onSortingChange:l,getCoreRowModel:G_(),getSortedRowModel:Z_()});return f.jsx(kC,{table:m})}const H$=vg({require_verification:Wx(),require_approval:Wx()});function B$(){const e=ka(),{data:t,error:r}=Ft({queryKey:["admin","policy"],queryFn:()=>qt("/api/admin/policy")}),{data:a}=A_(!0),o=lg({resolver:gg(H$),values:t?{require_verification:t.require_verification&&t.mailer,require_approval:t.require_approval}:{require_verification:!1,require_approval:!1}});if(S.useEffect(()=>{r&&qe(r.message,!0)},[r]),!t)return null;const l=async(u,d,m)=>{try{await ei(`/api/admin/pending/${u}/${d}`),qe((d==="approve"?"Approved ":"Denied ")+m),e.invalidateQueries({queryKey:["admin","pending"]})}catch(p){qe(p.message,!0)}};return f.jsxs("div",{className:"admin",children:[f.jsx("h1",{children:"Signup & access"}),f.jsx("p",{className:"admin-sub",children:"Who can create an account on this hub, and how new accounts are vetted."}),f.jsx("h3",{children:"New-account vetting"}),f.jsxs("form",{onSubmit:o.handleSubmit(async u=>{try{await ei("/api/admin/policy",u),qe("Signup policy saved."),e.invalidateQueries({queryKey:["admin","policy"]})}catch(d){qe(d.message,!0)}}),children:[f.jsxs("div",{className:"admin-list",children:[f.jsx(sw,{label:"Require email verification",desc:t.mailer?"New accounts must click an emailed link before they can sign in — proves they control the address.":"Configure SMTP on the server (auth.smtp) to enable email verification.",disabled:!t.mailer,inputProps:o.register("require_verification")}),f.jsx(sw,{label:"Require admin approval",desc:"New accounts wait for a hub admin to approve them before they gain access.",inputProps:o.register("require_approval")})]}),f.jsx(xt,{variant:"primary",type:"submit",style:{marginTop:14},disabled:!o.formState.isDirty,children:"Save policy"})]}),f.jsx("h3",{children:"Who can sign up"}),f.jsxs("div",{className:"admin-list",children:[f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:"Allowed email domains"}),f.jsx("span",{className:"ai-tag",children:t.allowed_domains&&t.allowed_domains.length?t.allowed_domains.map(u=>"@"+u).join(", "):"any"})]}),f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:"Self-signup"}),f.jsx("span",{className:"ai-tag",children:t.allow_signup?"open":"invite-only"})]}),f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:"Hub admins"}),f.jsx("span",{className:"ai-tag",children:t.admins&&t.admins.length?t.admins.join(", "):"none"})]})]}),f.jsx("p",{className:"admin-sub",children:"Domains and admins are set in the server config file (they can't be widened from the browser)."}),f.jsx("h3",{children:"Pending signups"}),f.jsxs("div",{className:"admin-list",children:[(!a||a.length===0)&&f.jsx("div",{className:"admin-empty",children:"No one is waiting for approval."}),(a||[]).map(u=>f.jsxs("div",{className:"admin-item",children:[f.jsx("span",{className:"ai-main",children:(u.name?u.name+" · ":"")+u.email}),f.jsx(xt,{variant:"primary",onClick:()=>l(u.id,"approve",u.email),children:"Approve"}),f.jsx("button",{className:"ai-del",onClick:()=>l(u.id,"deny",u.email),children:"Deny"})]},u.id))]})]})}function sw({label:e,desc:t,disabled:r,inputProps:a}){return f.jsxs("label",{className:"admin-item toggle",style:r?{opacity:.55}:void 0,children:[f.jsxs("span",{className:"ai-main",children:[f.jsx("div",{className:"tg-label",children:e}),f.jsx("div",{className:"tg-desc",children:t})]}),f.jsx("input",{type:"checkbox",disabled:r,...a})]})}function q$({...e}){return f.jsx(m1,{"data-slot":"select",...e})}function G$({...e}){return f.jsx(y1,{"data-slot":"select-value",...e})}function Z$({className:e,size:t="default",children:r,...a}){return f.jsxs(g1,{"data-slot":"select-trigger","data-size":t,className:We("flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",e),...a,children:[r,f.jsx(b1,{asChild:!0,children:f.jsx(Kp,{className:"size-4 opacity-50"})})]})}function K$({className:e,children:t,position:r="item-aligned",align:a="center",...o}){return f.jsx(w1,{children:f.jsxs(S1,{"data-slot":"select-content",className:We("relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",r==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",e),position:r,align:a,...o,children:[f.jsx(Q$,{}),f.jsx(j1,{className:We("p-1",r==="popper"&&"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"),children:t}),f.jsx(X$,{})]})})}function Y$({className:e,children:t,...r}){return f.jsxs(M1,{"data-slot":"select-item",className:We("relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",e),...r,children:[f.jsx("span",{"data-slot":"select-item-indicator",className:"absolute right-2 flex size-3.5 items-center justify-center",children:f.jsx(k1,{children:f.jsx(g_,{className:"size-4"})})}),f.jsx(N1,{children:t})]})}function Q$({className:e,...t}){return f.jsx(z1,{"data-slot":"select-scroll-up-button",className:We("flex cursor-default items-center justify-center py-1",e),...t,children:f.jsx(vk,{className:"size-4"})})}function X$({className:e,...t}){return f.jsx(L1,{"data-slot":"select-scroll-down-button",className:We("flex cursor-default items-center justify-center py-1",e),...t,children:f.jsx(Kp,{className:"size-4"})})}const ow=["#5b8def","#f5a623","#4cc38a","#e0679b","#8b7bf0","#3ec8c8","#e6934a"];function vl(e){let t=0;for(const r of e)t=t*31+r.charCodeAt(0)>>>0;return ow[t%ow.length]}function rm({projects:e,currentId:t,menu:r,onNew:a}){const o=e.find(l=>l.id===t);return f.jsxs("nav",{id:"projects","aria-label":"Projects",children:[f.jsxs("div",{className:"nav-head",children:[f.jsx("span",{children:"Projects"}),f.jsx("button",{className:"nav-add",title:"New project","aria-label":"New project",onClick:a,children:"+"})]}),f.jsx("div",{className:"proj-row",children:f.jsxs(q$,{value:t||"",onValueChange:l=>{l&&l!==t&&(Yt("/"+l),hr())},children:[f.jsxs(Z$,{id:"project-select","aria-label":`Switch project — current: ${o?.name??"none"}`,title:o?.name,className:"proj-trigger",children:[o&&f.jsx("span",{className:"proj-mark","aria-hidden":"true",style:{background:vl(o.name)},children:f.jsx(Vs,{name:o.icon})}),o?f.jsx("span",{"data-slot":"select-value",children:o.name}):f.jsx(G$,{placeholder:"Select a project"})]}),f.jsx(K$,{className:"proj-menu",position:"popper",sideOffset:4,children:e.map(l=>f.jsxs(Y$,{value:l.id,children:[f.jsx("span",{className:"proj-mark","aria-hidden":"true",style:{background:vl(l.name)},children:f.jsx(Vs,{name:l.icon})}),l.name]},l.id))})]})}),r&&f.jsx("ul",{className:"nav-menu","aria-label":"Project pages",children:[["dashboard","Dashboard","dashboard",r.onDashboard],["install","Installation","terminal",r.onInstall],["history","History","hist",r.onHistory],["settings","Settings","gear",r.onSettings]].map(([l,u,d,m])=>f.jsx("li",{children:f.jsxs("div",{id:"nav-"+l,className:"row"+(r.active===l?" active":""),role:"button",tabIndex:0,onClick:m,onKeyDown:p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),m())},children:[f.jsx(nt,{name:d}),f.jsx("span",{className:"label",children:u})]})},l))})]})}function FC({...e}){return f.jsx(YM,{"data-slot":"dropdown-menu",...e})}function VC({...e}){return f.jsx(QM,{"data-slot":"dropdown-menu-trigger",...e})}function UC({className:e,sideOffset:t=4,...r}){return f.jsx(XM,{children:f.jsx(JM,{"data-slot":"dropdown-menu-content",sideOffset:t,className:We("z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",e),...r})})}function Is({className:e,inset:t,variant:r="default",...a}){return f.jsx(eN,{"data-slot":"dropdown-menu-item","data-inset":t,"data-variant":r,className:We("relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground data-[variant=destructive]:*:[svg]:text-destructive!",e),...a})}function im({className:e,inset:t,...r}){return f.jsx(WM,{"data-slot":"dropdown-menu-label","data-inset":t,className:We("px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",e),...r})}const J$="https://github.com/runbear-io/beardrive";function W$(){return f.jsx("svg",{viewBox:"0 0 16 16",className:"gh-mark",fill:"currentColor","aria-hidden":"true",children:f.jsx("path",{d:"M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"})})}function eI({me:e,org:t,admin:r,orgActive:a,billing:o}){const l=e.name||e.email,[u,d]=S.useState(!1),m=t?Qs(t.manage_url):null,p=o?Qs(o.url):null;return f.jsxs("footer",{id:"accountbar",children:[f.jsxs("a",{className:"gh-star",href:J$,target:"_blank",rel:"noreferrer",children:[f.jsx(W$,{}),f.jsx("span",{children:"Star on GitHub"}),f.jsx("span",{className:"ext","aria-hidden":"true",children:"↗"}),f.jsx("span",{className:"sr-only",children:" (opens in a new tab)"})]}),f.jsxs(FC,{modal:!1,open:u,onOpenChange:d,children:[f.jsx(VC,{asChild:!0,children:f.jsxs("button",{id:"account-btn",className:a?"active":void 0,"aria-label":"Account menu",children:[f.jsx("span",{className:"avatar",style:{background:vl(e.email)},"aria-hidden":"true",children:(l.trim()[0]||"?").toUpperCase()}),f.jsxs("span",{className:"acct",children:[f.jsx("b",{children:l}),e.name&&f.jsx("small",{children:e.email})]}),f.jsx(nt,{name:"chev"})]})}),f.jsxs(UC,{id:"account-menu",side:"top",align:"start",sideOffset:6,className:"acct-menu",children:[t&&f.jsxs(f.Fragment,{children:[f.jsx(im,{className:"menu-sec",children:"Organization"}),f.jsx(Is,{asChild:!0,children:f.jsxs("a",{id:"menu-org-settings","aria-current":a?"page":void 0,...m,onClick:y=>{m?.onClick?.(y),d(!1)},children:[f.jsx(nt,{name:"gear"}),f.jsxs("span",{children:[f.jsx("b",{children:t.name})," Settings"]}),!t.manage_url.startsWith("/")&&f.jsxs(f.Fragment,{children:[f.jsx("span",{className:"ext","aria-hidden":"true",children:"↗"}),f.jsx("span",{className:"sr-only",children:" (opens in a new tab)"})]})]})}),o&&f.jsx(Is,{asChild:!0,children:f.jsxs("a",{id:"menu-billing",...p,onClick:y=>{p?.onClick?.(y),d(!1)},children:[f.jsx(nt,{name:"card"}),f.jsx("span",{children:"Billing"}),f.jsx("span",{className:"ps-chip plan-chip",children:o.plan})]})})]}),r&&f.jsxs(f.Fragment,{children:[f.jsx(im,{className:"menu-sec",children:"Hub"}),f.jsxs(Is,{id:"menu-hub-admin",onSelect:r.onClick,children:[f.jsx(nt,{name:"shield"}),f.jsxs("span",{children:["Signup & access",r.pending?` · ${r.pending}`:""]})]})]}),f.jsx(im,{className:"menu-sec",children:"Account"}),f.jsx(Is,{asChild:!0,children:f.jsxs("a",{id:"signout",href:"/auth/logout",children:[f.jsx(nt,{name:"power"}),f.jsx("span",{children:"Log out"})]})})]})]})]})}function Pi({className:e,...t}){return f.jsx("div",{"data-slot":"card",className:We("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",e),...t})}function Fi({className:e,...t}){return f.jsx("div",{"data-slot":"card-header",className:We("@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",e),...t})}function Vi({className:e,...t}){return f.jsx("div",{"data-slot":"card-title",className:We("leading-none font-semibold",e),...t})}function qs({className:e,...t}){return f.jsx("div",{"data-slot":"card-description",className:We("text-muted-foreground text-sm",e),...t})}function Ui({className:e,...t}){return f.jsx("div",{"data-slot":"card-content",className:We("px-6",e),...t})}function ti({className:e,orientation:t="horizontal",decorative:r=!0,...a}){return f.jsx(MN,{"data-slot":"separator",decorative:r,orientation:t,className:We("bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",e),...a})}function tI({url:e}){const t=Ft({queryKey:["billing"],queryFn:()=>qt(e)});if(t.isLoading)return f.jsx("div",{className:"empty",children:"Loading…"});if(t.error||!t.data)return f.jsxs("div",{className:"empty",children:[f.jsx("h3",{children:"Billing is unavailable"}),f.jsx("p",{children:t.error?.message||"Try again shortly."})]});const r=t.data;return f.jsxs("div",{className:"project-settings",id:"billing-view",children:[f.jsxs("h2",{children:["Billing",f.jsx("span",{className:"ps-chip plan-chip",children:r.plan.name})]}),f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsxs(Vi,{children:[r.plan.name," plan",r.plan.status?` (${r.plan.status})`:""]}),f.jsxs(qs,{children:["Organization ",r.org," · ",r.usage.used," of ",r.usage.cap," used · ",r.seats.used," of ",r.seats.cap," ",r.seats.cap===1?"seat":"seats"]})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsx("div",{className:"usage-bar",children:f.jsx("div",{style:{width:`${r.usage.pct}%`}})})})]}),r.owner?f.jsx("div",{className:"plan-grid",children:r.plans.map(a=>f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:a.name}),f.jsx(qs,{children:a.blurb})]}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsxs("p",{className:"plan-price",children:[a.price,f.jsx("small",{children:" / user / month"})]}),f.jsxs("form",{method:"post",action:r.checkout_url,children:[f.jsx("input",{type:"hidden",name:"plan",value:a.id}),f.jsx(xt,{type:"submit",disabled:a.current,variant:a.current?"subtle":"default",children:a.current?"Current plan":`Upgrade to ${a.name}`})]})]})]},a.id))}):f.jsx("p",{className:"muted-note",children:"Only an organization owner can change the plan."}),r.owner&&r.has_customer&&f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"Manage subscription"}),f.jsx(qs,{children:"Change seats, update the card, download invoices, or cancel."})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsx("form",{method:"post",action:r.portal_url,children:f.jsx(xt,{type:"submit",variant:"subtle",children:"Open the billing portal"})})})]})]})}function hu({className:e,type:t,...r}){return f.jsx("input",{type:t,"data-slot":"input",className:We("h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30","focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50","aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",e),...r})}function am({className:e,...t}){return f.jsx(nN,{"data-slot":"label",className:We("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",e),...t})}function nI({className:e,...t}){return f.jsx("textarea",{"data-slot":"textarea",className:We("border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",e),...t})}const lw={read:1,write:2,admin:3};function _a(e,t){return(lw[e||""]||0)>=(lw[t]||0)}const Wm=280,rI=vg({name:fu().trim().min(1,"Give the project a name.").max(120,"Keep the name under 120 characters."),description:fu().max(Wm,`Keep the description under ${Wm} characters.`),icon:fu()});function iI({project:e,org:t,onDeleted:r}){const a=M_(),o=_a(e.perm,"admin"),l=lg({resolver:gg(rI),defaultValues:{name:e.name,description:e.description??"",icon:e.icon??""}});S.useEffect(()=>{l.reset({name:e.name,description:e.description??"",icon:e.icon??""})},[e.id,e.name,e.description,e.icon]);const u=l.watch("icon"),d=l.watch("description"),m=l.handleSubmit(async p=>{const y=l.formState.dirtyFields,v={};if(y.name&&(v.name=p.name.trim()),y.description&&(v.description=p.description),y.icon&&(v.icon=p.icon),Object.keys(v).length!==0)try{await Wn("PATCH","/api/projects/"+e.id,v),qe("Saved."),l.reset({...p,name:p.name.trim()}),await a()}catch(b){qe(b.message,!0)}});return f.jsxs("div",{className:"project-settings",children:[f.jsxs("h2",{children:[e.name,!_a(e.perm,"write")&&f.jsx("span",{className:"ps-chip",children:"Read-only"})]}),f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"General"}),f.jsx(qs,{children:"Name, description and icon for this project."})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsxs("form",{className:"ps-form",onSubmit:m,children:[f.jsxs("div",{className:"ps-field",children:[f.jsx(am,{htmlFor:"ps-icon-btn",children:"Icon"}),f.jsxs("div",{className:"ps-icon-row",children:[f.jsx("span",{className:"proj-mark","aria-hidden":"true",style:{background:vl(e.name)},children:f.jsx(Vs,{name:u})}),f.jsxs(FC,{children:[f.jsx(VC,{asChild:!0,children:f.jsx(xt,{id:"ps-icon-btn",type:"button",variant:"subtle",disabled:!o,children:"Change"})}),f.jsxs(UC,{align:"start",className:"ps-icon-grid",children:[f.jsx(Is,{className:"ps-icon-cell"+(u===""?" active":""),title:"Default","aria-label":"Default icon",onSelect:()=>l.setValue("icon","",{shouldDirty:!0}),children:f.jsx(Vs,{})}),Object.keys(Lm).map(p=>f.jsx(Is,{className:"ps-icon-cell"+(u===p?" active":""),title:p,"aria-label":p,onSelect:()=>l.setValue("icon",p,{shouldDirty:!0}),children:f.jsx(Vs,{name:p})},p))]})]})]})]}),f.jsxs("div",{className:"ps-field",children:[f.jsx(am,{htmlFor:"ps-name",children:"Name"}),f.jsx(hu,{id:"ps-name",disabled:!o,"aria-invalid":!!l.formState.errors.name,"aria-describedby":l.formState.errors.name?"ps-name-err":void 0,...l.register("name")}),l.formState.errors.name&&f.jsx("span",{id:"ps-name-err",role:"alert",className:"field-err",children:l.formState.errors.name.message})]}),f.jsxs("div",{className:"ps-field",children:[f.jsxs(am,{htmlFor:"ps-desc",children:["Description ",f.jsx("span",{className:"ps-opt",children:"(optional)"})]}),f.jsx(nI,{id:"ps-desc",rows:2,disabled:!o,placeholder:"What this project is for.","aria-invalid":!!l.formState.errors.description,"aria-describedby":l.formState.errors.description?"ps-desc-err":void 0,...l.register("description")}),f.jsxs("div",{className:"ps-meta",children:[l.formState.errors.description?f.jsx("span",{id:"ps-desc-err",role:"alert",className:"field-err",children:l.formState.errors.description.message}):f.jsx("span",{}),f.jsxs("span",{className:"ps-count",children:[d.length," / ",Wm]})]})]}),o&&f.jsxs(f.Fragment,{children:[f.jsx(ti,{}),f.jsx("div",{className:"ps-actions",children:f.jsx(xt,{id:"ps-save",type:"submit",variant:"primary",disabled:!l.formState.isDirty||l.formState.isSubmitting,children:"Save changes"})})]})]})})]}),f.jsx(aI,{project:e}),f.jsx(oI,{project:e,org:t}),f.jsxs(Pi,{children:[f.jsx(Fi,{children:f.jsx(Vi,{children:"About"})}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsxs("dl",{className:"ps-facts",children:[f.jsx("dt",{children:"Project id"}),f.jsx("dd",{children:f.jsx("code",{children:e.id})}),t&&f.jsxs(f.Fragment,{children:[f.jsx("dt",{children:"Workspace"}),f.jsx("dd",{children:t.name})]}),e.created&&f.jsxs(f.Fragment,{children:[f.jsx("dt",{children:"Created"}),f.jsx("dd",{children:new Date(e.created).toLocaleDateString()})]})]}),f.jsxs("p",{className:"ps-note ps-export",children:[f.jsx("strong",{children:"Take your files elsewhere."})," Run ",f.jsx("code",{children:"bdrive export"})," in the synced folder to write the whole project — every device's journal and every content blob, so full history and authorship — into a single archive. ",f.jsx("code",{children:"bdrive import"})," restores it into any other BearDrive hub, self-hosted or cloud. Export warns first if this device still has changes it hasn't pushed."," ",f.jsx("a",{href:"https://docs.beardrive.ai/reference/migration/",target:"_blank",rel:"noreferrer",children:"How migration works →"})]})]})]}),o&&f.jsxs(Pi,{className:"ps-danger",children:[f.jsx(Fi,{children:f.jsx(Vi,{children:"Danger zone"})}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsx("p",{children:"Deleting removes the project from this hub. Its files stay in storage. This can't be undone."}),f.jsx(xt,{variant:"danger",onClick:async()=>{if(await T_(`Delete “${e.name}”?`,"This can't be undone. Type the project name to confirm:","","Delete project",{match:e.name,danger:!0})!==null)try{await Wn("DELETE","/api/projects/"+e.id),qe(`Deleted “${e.name}”.`),await r()}catch(y){qe(y.message,!0)}},children:"Delete project"})]})]})]})}function aI({project:e}){const t=ka(),{data:r,error:a,isLoading:o}=O_(e.id);return a?null:f.jsxs(Pi,{children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"Public links"}),f.jsxs(qs,{children:["Files in this project that anyone with the URL can read — no account needed.",(r||[]).some(l=>l.opens!==void 0)&&f.jsxs(f.Fragment,{children:[" ",$C]})]})]}),f.jsx(ti,{}),f.jsx(Ui,{children:f.jsx(IC,{shares:r||[],loading:o,canRevoke:_a(e.perm,"write"),onChanged:()=>t.invalidateQueries({queryKey:["shares",e.id]}),empty:"No public links."})})]})}const ep=[{value:"admin",label:"Admin"},{value:"write",label:"Write"},{value:"read",label:"Read"},{value:"none",label:"No access"}],sI=Object.fromEntries(ep.map(e=>[e.value,e.label]));function oI({project:e,org:t}){const r=ka(),{data:a,error:o}=k3(e.id),l=_a(e.perm,"admin"),u=()=>{r.invalidateQueries({queryKey:["permissions",e.id]}),r.invalidateQueries({queryKey:["projects"]})},d=async(x,w)=>{try{await x(),qe(w)}catch(_){qe(_.message,!0)}u()};if(o||!a)return null;const m=a,p=`/api/p/${e.id}/permissions`,y=new Set((t?.members||[]).filter(x=>x.role==="owner").map(x=>x.email.toLowerCase())),v=[...m.grants.filter(x=>!y.has(x.email.toLowerCase())),...[...y].sort().map(x=>({email:x,level:"admin",owner:!0}))],b=async()=>{const x=await T_("Add an exception","Email of a workspace member. They get Read access; change it in the table.","","Add");x===null||!x.trim()||await d(()=>Wn("PUT",`${p}/${encodeURIComponent(x.trim())}`,{level:"read"}),"Added.")};return f.jsxs(Pi,{className:"ps-people",children:[f.jsxs(Fi,{children:[f.jsx(Vi,{children:"People"}),f.jsx(qs,{children:"Who can see and change this project."})]}),f.jsx(ti,{}),f.jsxs(Ui,{children:[f.jsxs("p",{className:"ps-row",children:[f.jsxs("span",{children:["Everyone in ",t?.name||"this workspace"," can"]}),f.jsx("select",{"aria-label":"Default access for workspace members",disabled:!l,value:m.default,onChange:async x=>{const w=x.target.value;if(w==="none"&&!await zi("Make this project invite-only?","Only people listed below (and workspace owners) will see this project.","Make invite-only")){u();return}await d(()=>Wn("PUT",p,{default:w}),"Default access updated.")},children:ep.filter(x=>x.value!=="admin").map(x=>f.jsx("option",{value:x.value,children:x.label},x.value))})]}),m.default==="none"&&f.jsx("p",{className:"ps-note",children:"This project is invite-only: only the people below and workspace owners can see it."}),f.jsxs("div",{className:"ps-people-head",children:[f.jsx("h4",{children:"Exceptions"}),l&&f.jsx(xt,{type:"button",variant:"subtle",onClick:b,children:"+ Add"})]}),v.length===0?f.jsx("p",{className:"ps-note",children:"No exceptions — everyone gets the access above."}):f.jsx("div",{className:"admin-list",children:v.map(x=>{const w="owner"in x;return f.jsxs("div",{className:"admin-item",children:[f.jsxs("span",{className:"ai-main",title:x.email,children:[x.email,m.creator&&x.email.toLowerCase()===m.creator.toLowerCase()&&f.jsx("span",{className:"ai-tag",children:" (creator)"})]}),w?f.jsx("span",{className:"ai-tag",children:"Workspace owner — always admin"}):f.jsxs("span",{className:"role-cell",children:[f.jsx("select",{"aria-label":`Access for ${x.email}`,disabled:!l,value:x.level,onChange:_=>d(()=>Wn("PUT",`${p}/${encodeURIComponent(x.email)}`,{level:_.target.value}),`${x.email} is now ${sI[_.target.value]||_.target.value}.`),children:ep.map(_=>f.jsx("option",{value:_.value,children:_.label},_.value))}),l&&f.jsx("button",{className:"ai-del","aria-label":`Remove exception for ${x.email}`,onClick:()=>d(()=>Wn("DELETE",`${p}/${encodeURIComponent(x.email)}`),"Reverted to the default access."),children:"Remove"})]})]},x.email)})})]})]})}const HC="https://raw.githubusercontent.com/runbear-io/beardrive/main/INSTALL_FOR_AGENTS.md";function BC({project:e,existing:t}){const r=window.location.origin,a=t?'. I already have a folder of notes — ask me which one to sync (the project is named "':'. Ask me which folder to sync (the project is named "',o="Follow "+HC+` to set up BearDrive project `+e.id+" on "+r+a+e.name+'").',l=`brew install runbear-io/tap/beardrive bdrive login `+r+` bdrive init --project `+e.id;return f.jsxs("div",{className:"guide",children:[f.jsxs("h1",{className:"in-title gd-head",children:[f.jsx("span",{className:"proj-mark","aria-hidden":"true",style:{background:vl(e.name)},children:f.jsx(Vs,{name:e.icon})}),e.name]}),e.description&&f.jsx("p",{className:"in-desc",children:e.description}),f.jsxs("div",{className:"gd-body",children:[f.jsx("p",{className:"gd-desc",children:t?"Paste into your coding agent — Claude Code, Cowork, Codex, Gemini CLI, Hermes — in the folder you already have:":"Paste into your coding agent — Claude Code, Cowork, Codex, Gemini CLI, Hermes — in the folder where you want the files:"}),t&&f.jsx("p",{className:"gd-note",children:"Your files stay exactly where they are. Connecting a folder never moves, renames or overwrites anything in it — it uploads what is there and keeps it in sync."}),f.jsx(tp,{code:o}),f.jsx("p",{className:"gd-desc",children:"The agent installs the CLI, signs this machine in, and registers the sync hooks — asking before anything it changes."}),f.jsx("p",{className:"gd-desc",children:"Runs on macOS and Linux. Windows is not supported yet."}),f.jsxs("details",{className:"gd-manual",children:[f.jsx("summary",{children:"What exactly happens"}),f.jsxs("ul",{className:"gd-desc gd-list",children:[f.jsx("li",{children:"Sign-in uses a device code you approve in this browser — the folder itself never holds credentials."}),f.jsx("li",{children:"Sync hooks pull the latest before every agent turn, push edits seconds after they happen, and stamp each change with the session that made it; agent reads feed Insights. They register once per machine in your agent's own config, so every session is covered and nothing is written into the synced folder."}),f.jsx("li",{children:"Codex hooks are off by default: set [features] codex_hooks = true in ~/.codex/config.toml."})]})]}),f.jsxs("details",{className:"gd-manual",children:[f.jsx("summary",{children:"Or run it yourself"}),f.jsx("p",{className:"gd-desc",children:"Same result, in the folder you want the files. Install the CLI, point it at this hub, then bdrive init registers the sync hooks and starts syncing."}),f.jsx(tp,{code:l}),f.jsx("p",{className:"gd-desc",children:f.jsx("a",{href:"https://docs.beardrive.ai/manual/install/",target:"_blank",rel:"noreferrer",children:"Full manual setup guide →"})})]})]})]})}function tp({code:e}){const[t,r]=S.useState("Copy");return f.jsxs("pre",{className:"gd-code",children:[f.jsx("code",{children:e}),f.jsx("button",{className:"gd-copy",onClick:async()=>{r(await Na(e)?"Copied":"Copy failed"),setTimeout(()=>r("Copy"),1400)},children:t})]})}function lI({onNew:e,canCreate:t}){return f.jsxs("div",{className:"onboard",children:[f.jsx("h1",{children:"Welcome to BearDrive"}),f.jsx("p",{children:"You're signed in, but you're not part of any project yet."}),t&&f.jsxs("div",{className:"ob-card ob-start",children:[f.jsx("h3",{children:"Start a project"}),f.jsx("p",{children:"Name it and pick what it starts from — a structure, or nothing at all. Then connect a folder on any machine and it stays in sync."}),f.jsx(xt,{variant:"primary",id:"ob-new",onClick:e,children:"New project"})]}),f.jsxs("div",{className:"ob-card ob-agent",children:[f.jsx("h3",{children:t?"Or let your agent do it":"Connect a new drive to your project"}),f.jsx("p",{children:"Paste into your coding agent — Claude Code, Cowork, Codex, Gemini CLI, Hermes — in the folder where you want the files. It creates the project and starts syncing:"}),f.jsx(tp,{code:"Follow "+HC+` diff --git a/internal/webapp/static/index.html b/internal/webapp/static/index.html index 1427f2f..359f644 100644 --- a/internal/webapp/static/index.html +++ b/internal/webapp/static/index.html @@ -5,7 +5,7 @@ BearDrive - +