[{"data":1,"prerenderedAt":3819},["ShallowReactive",2],{"navigation":3,"\u002Fcore\u002Fnoydb\u002Fauthentication":927,"mdc-onvxjk-key":3772},[4,40,114,446,474,498,596,903],{"title":5,"path":6,"stem":7,"children":8},"Architecture","\u002Farchitecture","architecture",[9,14,28,32,36],{"title":10,"path":6,"stem":11,"access":12,"icon":13},"Overview","architecture\u002Findex","public","i-lucide-network",{"title":10,"path":15,"stem":16,"children":17,"access":12,"icon":19},"\u002Farchitecture\u002Fkernel","architecture\u002F1.kernel\u002Findex",[18,20,24],{"title":10,"path":15,"stem":16,"access":12,"icon":19},"i-lucide-box",{"title":21,"path":22,"stem":23,"access":12},"Enclave","\u002Farchitecture\u002Fkernel\u002Fenclave","architecture\u002F1.kernel\u002Fenclave",{"title":25,"path":26,"stem":27,"access":12},"Forking the enclave","\u002Farchitecture\u002Fkernel\u002Fforking-the-enclave","architecture\u002F1.kernel\u002Fforking-the-enclave",{"title":29,"path":30,"stem":31,"access":12},"Ports","\u002Farchitecture\u002Fports","architecture\u002F2.ports",{"title":33,"path":34,"stem":35,"access":12},"Service layers","\u002Farchitecture\u002Fservice-layers","architecture\u002F3.service-layers",{"title":37,"path":38,"stem":39,"access":12},"Families","\u002Farchitecture\u002Ffamilies","architecture\u002F4.families",{"title":41,"path":42,"stem":43,"children":44},"Core","\u002Fcore","core",[45,47,50,53,56,88,97],{"title":10,"path":42,"stem":46,"access":12,"icon":19},"core\u002Findex",{"title":10,"path":48,"stem":49,"access":12},"\u002Fcore\u002F01-overview","core\u002F01-overview",{"title":10,"path":51,"stem":52,"access":12},"\u002Fcore\u002F05-stores","core\u002F05-stores",{"title":10,"path":54,"stem":55,"access":12},"\u002Fcore\u002F06-permissions-and-keyring","core\u002F06-permissions-and-keyring",{"title":10,"path":57,"stem":58,"children":59,"access":12},"\u002Fcore\u002Fnoydb","core\u002F2.noydb\u002Findex",[60,61,65,68,72,76,80,84],{"title":10,"path":57,"stem":58,"access":12},{"title":62,"path":63,"stem":64,"access":12},"Noydb","\u002Fcore\u002Fnoydb\u002Fmethods","core\u002F2.noydb\u002F1.methods",{"title":21,"path":66,"stem":67,"access":12},"\u002Fcore\u002Fnoydb\u002Fenclave","core\u002F2.noydb\u002F2.enclave",{"title":69,"path":70,"stem":71,"access":12},"Secret & keyring","\u002Fcore\u002Fnoydb\u002Fkeyring","core\u002F2.noydb\u002F3.keyring",{"title":73,"path":74,"stem":75,"access":12},"Authentication","\u002Fcore\u002Fnoydb\u002Fauthentication","core\u002F2.noydb\u002F4.authentication",{"title":77,"path":78,"stem":79,"access":12},"Auth recovery","\u002Fcore\u002Fnoydb\u002Frecovery","core\u002F2.noydb\u002F5.recovery",{"title":81,"path":82,"stem":83,"access":12},"Configuration","\u002Fcore\u002Fnoydb\u002Fconfiguration","core\u002F2.noydb\u002F6.configuration",{"title":85,"path":86,"stem":87,"access":12},"Strategies","\u002Fcore\u002Fnoydb\u002Fstrategies","core\u002F2.noydb\u002F7.strategies",{"title":10,"path":89,"stem":90,"children":91,"access":12},"\u002Fcore\u002Fvault","core\u002F3.vault\u002Findex",[92,93],{"title":10,"path":89,"stem":90,"access":12},{"title":94,"path":95,"stem":96,"access":12},"Vault","\u002Fcore\u002Fvault\u002Fmethods","core\u002F3.vault\u002F1.methods",{"title":10,"path":98,"stem":99,"children":100,"access":12},"\u002Fcore\u002Fcollection","core\u002F4.collection\u002Findex",[101,102,106,110],{"title":10,"path":98,"stem":99,"access":12},{"title":103,"path":104,"stem":105,"access":12},"Collection","\u002Fcore\u002Fcollection\u002Fmethods","core\u002F4.collection\u002F1.methods",{"title":107,"path":108,"stem":109,"access":12},"Querying","\u002Fcore\u002Fcollection\u002Fquerying","core\u002F4.collection\u002F2.querying",{"title":111,"path":112,"stem":113,"access":12},"Schema","\u002Fcore\u002Fcollection\u002Fschema","core\u002F4.collection\u002F3.schema",{"title":37,"path":115,"stem":116,"children":117},"\u002Ffamilies","families",[118,121,168,194,208,212,216,294,340],{"title":10,"path":115,"stem":119,"access":12,"icon":120},"families\u002Findex","i-lucide-plug",{"title":122,"path":123,"stem":124,"children":125,"access":12,"icon":127},"as-Exports","\u002Ffamilies\u002Fas","families\u002Fas\u002Findex",[126,128,132,136,140,144,148,152,156,160,164],{"title":122,"path":123,"stem":124,"access":12,"icon":127},"i-lucide-book-open",{"title":129,"path":130,"stem":131,"access":12},"aws-s3","\u002Ffamilies\u002Fas\u002Faws-s3","families\u002Fas\u002Faws-s3",{"title":133,"path":134,"stem":135,"access":12},"blob","\u002Ffamilies\u002Fas\u002Fblob","families\u002Fas\u002Fblob",{"title":137,"path":138,"stem":139,"access":12},"csv","\u002Ffamilies\u002Fas\u002Fcsv","families\u002Fas\u002Fcsv",{"title":141,"path":142,"stem":143,"access":12},"json","\u002Ffamilies\u002Fas\u002Fjson","families\u002Fas\u002Fjson",{"title":145,"path":146,"stem":147,"access":12},"ndjson","\u002Ffamilies\u002Fas\u002Fndjson","families\u002Fas\u002Fndjson",{"title":149,"path":150,"stem":151,"access":12},"noydb","\u002Ffamilies\u002Fas\u002Fnoydb","families\u002Fas\u002Fnoydb",{"title":153,"path":154,"stem":155,"access":12},"sql","\u002Ffamilies\u002Fas\u002Fsql","families\u002Fas\u002Fsql",{"title":157,"path":158,"stem":159,"access":12},"xlsx","\u002Ffamilies\u002Fas\u002Fxlsx","families\u002Fas\u002Fxlsx",{"title":161,"path":162,"stem":163,"access":12},"xml","\u002Ffamilies\u002Fas\u002Fxml","families\u002Fas\u002Fxml",{"title":165,"path":166,"stem":167,"access":12},"zip","\u002Ffamilies\u002Fas\u002Fzip","families\u002Fas\u002Fzip",{"title":169,"path":170,"stem":171,"children":172,"access":12,"icon":127},"at-Seals","\u002Ffamilies\u002Fat","families\u002Fat\u002Findex",[173,174,178,182,186,190],{"title":169,"path":170,"stem":171,"access":12,"icon":127},{"title":175,"path":176,"stem":177,"access":12},"aws-kms","\u002Ffamilies\u002Fat\u002Faws-kms","families\u002Fat\u002Faws-kms",{"title":179,"path":180,"stem":181,"access":12},"azure-keyvault","\u002Ffamilies\u002Fat\u002Fazure-keyvault","families\u002Fat\u002Fazure-keyvault",{"title":183,"path":184,"stem":185,"access":12},"env","\u002Ffamilies\u002Fat\u002Fenv","families\u002Fat\u002Fenv",{"title":187,"path":188,"stem":189,"access":12},"gcp-kms","\u002Ffamilies\u002Fat\u002Fgcp-kms","families\u002Fat\u002Fgcp-kms",{"title":191,"path":192,"stem":193,"access":12},"macos-keychain","\u002Ffamilies\u002Fat\u002Fmacos-keychain","families\u002Fat\u002Fmacos-keychain",{"title":195,"path":196,"stem":197,"children":198,"access":12,"icon":127},"by-Sessions","\u002Ffamilies\u002Fby","families\u002Fby\u002Findex",[199,200,204],{"title":195,"path":196,"stem":197,"access":12,"icon":127},{"title":201,"path":202,"stem":203,"access":12},"peer","\u002Ffamilies\u002Fby\u002Fpeer","families\u002Fby\u002Fpeer",{"title":205,"path":206,"stem":207,"access":12},"tabs","\u002Ffamilies\u002Fby\u002Ftabs","families\u002Fby\u002Ftabs",{"title":209,"path":210,"stem":211,"access":12},"Classifying a package","\u002Ffamilies\u002Fclassification","families\u002Fclassification",{"title":213,"path":214,"stem":215,"access":12},"Command-line tools","\u002Ffamilies\u002Fcli","families\u002Fcli",{"title":217,"path":218,"stem":219,"children":220,"access":12,"icon":127},"in-Frameworks","\u002Ffamilies\u002Fin","families\u002Fin\u002Findex",[221,222,226,230,234,238,242,246,250,254,258,262,266,270,274,278,282,286,290],{"title":217,"path":218,"stem":219,"access":12,"icon":127},{"title":223,"path":224,"stem":225,"access":12},"ai","\u002Ffamilies\u002Fin\u002Fai","families\u002Fin\u002Fai",{"title":227,"path":228,"stem":229,"access":12},"devtools","\u002Ffamilies\u002Fin\u002Fdevtools","families\u002Fin\u002Fdevtools",{"title":231,"path":232,"stem":233,"access":12},"devtools-tui","\u002Ffamilies\u002Fin\u002Fdevtools-tui","families\u002Fin\u002Fdevtools-tui",{"title":235,"path":236,"stem":237,"access":12},"liff","\u002Ffamilies\u002Fin\u002Fliff","families\u002Fin\u002Fliff",{"title":239,"path":240,"stem":241,"access":12},"nextjs","\u002Ffamilies\u002Fin\u002Fnextjs","families\u002Fin\u002Fnextjs",{"title":243,"path":244,"stem":245,"access":12},"nuxt","\u002Ffamilies\u002Fin\u002Fnuxt","families\u002Fin\u002Fnuxt",{"title":247,"path":248,"stem":249,"access":12},"pinia","\u002Ffamilies\u002Fin\u002Fpinia","families\u002Fin\u002Fpinia",{"title":251,"path":252,"stem":253,"access":12},"pwa","\u002Ffamilies\u002Fin\u002Fpwa","families\u002Fin\u002Fpwa",{"title":255,"path":256,"stem":257,"access":12},"react","\u002Ffamilies\u002Fin\u002Freact","families\u002Fin\u002Freact",{"title":259,"path":260,"stem":261,"access":12},"relay","\u002Ffamilies\u002Fin\u002Frelay","families\u002Fin\u002Frelay",{"title":263,"path":264,"stem":265,"access":12},"rest","\u002Ffamilies\u002Fin\u002Frest","families\u002Fin\u002Frest",{"title":267,"path":268,"stem":269,"access":12},"solid","\u002Ffamilies\u002Fin\u002Fsolid","families\u002Fin\u002Fsolid",{"title":271,"path":272,"stem":273,"access":12},"svelte","\u002Ffamilies\u002Fin\u002Fsvelte","families\u002Fin\u002Fsvelte",{"title":275,"path":276,"stem":277,"access":12},"tanstack-query","\u002Ffamilies\u002Fin\u002Ftanstack-query","families\u002Fin\u002Ftanstack-query",{"title":279,"path":280,"stem":281,"access":12},"tanstack-table","\u002Ffamilies\u002Fin\u002Ftanstack-table","families\u002Fin\u002Ftanstack-table",{"title":283,"path":284,"stem":285,"access":12},"vue","\u002Ffamilies\u002Fin\u002Fvue","families\u002Fin\u002Fvue",{"title":287,"path":288,"stem":289,"access":12},"yjs","\u002Ffamilies\u002Fin\u002Fyjs","families\u002Fin\u002Fyjs",{"title":291,"path":292,"stem":293,"access":12},"zustand","\u002Ffamilies\u002Fin\u002Fzustand","families\u002Fin\u002Fzustand",{"title":295,"path":296,"stem":297,"children":298,"access":12,"icon":127},"on-Auth","\u002Ffamilies\u002Fon","families\u002Fon\u002Findex",[299,300,304,308,312,316,320,324,328,332,336],{"title":295,"path":296,"stem":297,"access":12,"icon":127},{"title":301,"path":302,"stem":303,"access":12},"email-otp","\u002Ffamilies\u002Fon\u002Femail-otp","families\u002Fon\u002Femail-otp",{"title":305,"path":306,"stem":307,"access":12},"magic-link","\u002Ffamilies\u002Fon\u002Fmagic-link","families\u002Fon\u002Fmagic-link",{"title":309,"path":310,"stem":311,"access":12},"oidc","\u002Ffamilies\u002Fon\u002Foidc","families\u002Fon\u002Foidc",{"title":313,"path":314,"stem":315,"access":12},"password","\u002Ffamilies\u002Fon\u002Fpassword","families\u002Fon\u002Fpassword",{"title":317,"path":318,"stem":319,"access":12},"pin","\u002Ffamilies\u002Fon\u002Fpin","families\u002Fon\u002Fpin",{"title":321,"path":322,"stem":323,"access":12},"recovery","\u002Ffamilies\u002Fon\u002Frecovery","families\u002Fon\u002Frecovery",{"title":325,"path":326,"stem":327,"access":12},"shamir","\u002Ffamilies\u002Fon\u002Fshamir","families\u002Fon\u002Fshamir",{"title":329,"path":330,"stem":331,"access":12},"threat","\u002Ffamilies\u002Fon\u002Fthreat","families\u002Fon\u002Fthreat",{"title":333,"path":334,"stem":335,"access":12},"totp","\u002Ffamilies\u002Fon\u002Ftotp","families\u002Fon\u002Ftotp",{"title":337,"path":338,"stem":339,"access":12},"webauthn","\u002Ffamilies\u002Fon\u002Fwebauthn","families\u002Fon\u002Fwebauthn",{"title":341,"path":342,"stem":343,"children":344,"access":12,"icon":127},"to-Stores","\u002Ffamilies\u002Fto","families\u002Fto\u002Findex",[345,346,350,353,357,361,365,370,374,378,382,386,390,394,398,402,406,410,414,417,421,425,429,434,438,442],{"title":341,"path":342,"stem":343,"access":12,"icon":127},{"title":347,"path":348,"stem":349,"access":12},"aws-dynamo","\u002Ffamilies\u002Fto\u002Faws-dynamo","families\u002Fto\u002Faws-dynamo",{"title":129,"path":351,"stem":352,"access":12},"\u002Ffamilies\u002Fto\u002Faws-s3","families\u002Fto\u002Faws-s3",{"title":354,"path":355,"stem":356,"access":12},"browser-fs","\u002Ffamilies\u002Fto\u002Fbrowser-fs","families\u002Fto\u002Fbrowser-fs",{"title":358,"path":359,"stem":360,"access":12},"browser-idb","\u002Ffamilies\u002Fto\u002Fbrowser-idb","families\u002Fto\u002Fbrowser-idb",{"title":362,"path":363,"stem":364,"access":12},"browser-local","\u002Ffamilies\u002Fto\u002Fbrowser-local","families\u002Fto\u002Fbrowser-local",{"title":366,"path":367,"stem":368,"access":12,"icon":369},"Choosing a store","\u002Ffamilies\u002Fto\u002Fchoosing-a-store","families\u002Fto\u002Fchoosing-a-store","i-lucide-split",{"title":371,"path":372,"stem":373,"access":12},"cloudflare-d1","\u002Ffamilies\u002Fto\u002Fcloudflare-d1","families\u002Fto\u002Fcloudflare-d1",{"title":375,"path":376,"stem":377,"access":12},"cloudflare-r2","\u002Ffamilies\u002Fto\u002Fcloudflare-r2","families\u002Fto\u002Fcloudflare-r2",{"title":379,"path":380,"stem":381,"access":12},"drive","\u002Ffamilies\u002Fto\u002Fdrive","families\u002Fto\u002Fdrive",{"title":383,"path":384,"stem":385,"access":12},"file","\u002Ffamilies\u002Fto\u002Ffile","families\u002Fto\u002Ffile",{"title":387,"path":388,"stem":389,"access":12},"icloud","\u002Ffamilies\u002Fto\u002Ficloud","families\u002Fto\u002Ficloud",{"title":391,"path":392,"stem":393,"access":12},"memory","\u002Ffamilies\u002Fto\u002Fmemory","families\u002Fto\u002Fmemory",{"title":395,"path":396,"stem":397,"access":12},"meter","\u002Ffamilies\u002Fto\u002Fmeter","families\u002Fto\u002Fmeter",{"title":399,"path":400,"stem":401,"access":12},"mysql","\u002Ffamilies\u002Fto\u002Fmysql","families\u002Fto\u002Fmysql",{"title":403,"path":404,"stem":405,"access":12},"nfs","\u002Ffamilies\u002Fto\u002Fnfs","families\u002Fto\u002Fnfs",{"title":407,"path":408,"stem":409,"access":12},"postgres","\u002Ffamilies\u002Fto\u002Fpostgres","families\u002Fto\u002Fpostgres",{"title":411,"path":412,"stem":413,"access":12},"probe","\u002Ffamilies\u002Fto\u002Fprobe","families\u002Fto\u002Fprobe",{"title":263,"path":415,"stem":416,"access":12},"\u002Ffamilies\u002Fto\u002Frest","families\u002Fto\u002Frest",{"title":418,"path":419,"stem":420,"access":12},"smb","\u002Ffamilies\u002Fto\u002Fsmb","families\u002Fto\u002Fsmb",{"title":422,"path":423,"stem":424,"access":12},"sqlite","\u002Ffamilies\u002Fto\u002Fsqlite","families\u002Fto\u002Fsqlite",{"title":426,"path":427,"stem":428,"access":12},"ssh","\u002Ffamilies\u002Fto\u002Fssh","families\u002Fto\u002Fssh",{"title":430,"path":431,"stem":432,"access":12,"icon":433},"Store-locator descriptors","\u002Ffamilies\u002Fto\u002Fstore-locator","families\u002Fto\u002Fstore-locator","i-lucide-map-pin",{"title":435,"path":436,"stem":437,"access":12},"supabase","\u002Ffamilies\u002Fto\u002Fsupabase","families\u002Fto\u002Fsupabase",{"title":439,"path":440,"stem":441,"access":12},"turso","\u002Ffamilies\u002Fto\u002Fturso","families\u002Fto\u002Fturso",{"title":443,"path":444,"stem":445,"access":12},"webdav","\u002Ffamilies\u002Fto\u002Fwebdav","families\u002Fto\u002Fwebdav",{"title":447,"path":448,"stem":449,"children":450},"Faq","\u002Ffaq","faq",[451,454,458,462,466,470],{"title":10,"path":448,"stem":452,"access":12,"icon":453},"faq\u002Findex","i-lucide-circle-help",{"title":455,"path":456,"stem":457,"access":12},"Where can noy-db run?","\u002Ffaq\u002Fwhere-can-noy-db-run","faq\u002F1.where-can-noy-db-run",{"title":459,"path":460,"stem":461,"access":12},"Native mobile & PWA","\u002Ffaq\u002Fmobile-and-pwa","faq\u002F2.mobile-and-pwa",{"title":463,"path":464,"stem":465,"access":12},"Threat model","\u002Ffaq\u002Fthreat-model","faq\u002F3.threat-model",{"title":467,"path":468,"stem":469,"access":12},"Community & ecosystem","\u002Ffaq\u002Fcommunity-and-ecosystem","faq\u002F4.community-and-ecosystem",{"title":471,"path":472,"stem":473,"access":12},"Licensing","\u002Ffaq\u002Flicensing","faq\u002F5.licensing",{"title":475,"path":476,"stem":477,"children":478},"Glossary","\u002Fglossary","glossary",[479,482,486,490,494],{"title":10,"path":476,"stem":480,"access":12,"icon":481},"glossary\u002Findex","i-lucide-book-a",{"title":483,"path":484,"stem":485,"access":12},"Core vocabulary","\u002Fglossary\u002Fcore-vocabulary","glossary\u002Fcore-vocabulary",{"title":487,"path":488,"stem":489,"access":12},"Deletion vocabulary","\u002Fglossary\u002Fdeletion","glossary\u002Fdeletion",{"title":491,"path":492,"stem":493,"access":12},"Satellite collection vocabulary","\u002Fglossary\u002Fsatellite-collections","glossary\u002Fsatellite-collections",{"title":495,"path":496,"stem":497,"access":12},"Schema migration vocabulary","\u002Fglossary\u002Fschema-migration","glossary\u002Fschema-migration",{"title":499,"path":500,"stem":501,"children":502},"Recipes","\u002Frecipes","recipes",[503,506,510,514,518,522,526,530,534,538,542,546,550,554,558,562,567,571,575,580,584,588,592],{"title":10,"path":500,"stem":504,"access":12,"icon":505},"recipes\u002Findex","i-lucide-play",{"title":507,"path":508,"stem":509,"access":12},"Accounting app","\u002Frecipes\u002Faccounting-app","recipes\u002Faccounting-app",{"title":511,"path":512,"stem":513,"access":12},"Analytics app","\u002Frecipes\u002Fanalytics-app","recipes\u002Fanalytics-app",{"title":515,"path":516,"stem":517,"access":12},"Attestation verifier","\u002Frecipes\u002Fattestation-verifier","recipes\u002Fattestation-verifier",{"title":519,"path":520,"stem":521,"access":12},"AWS-KMS attestation","\u002Frecipes\u002Faws-kms-pdf-attestation","recipes\u002Faws-kms-pdf-attestation",{"title":523,"path":524,"stem":525,"access":12},"Browser durability","\u002Frecipes\u002Fbrowser-durability","recipes\u002Fbrowser-durability",{"title":527,"path":528,"stem":529,"access":12},"Production cloud store","\u002Frecipes\u002Fcloud-store","recipes\u002Fcloud-store",{"title":531,"path":532,"stem":533,"access":12},"Compose your own setup","\u002Frecipes\u002Fcompose-your-own","recipes\u002Fcompose-your-own",{"title":535,"path":536,"stem":537,"access":12},"Confidential HR records","\u002Frecipes\u002Fconfidential-hr","recipes\u002Fconfidential-hr",{"title":539,"path":540,"stem":541,"access":12},"Composing an echo secret","\u002Frecipes\u002Fecho-secret-enrollment","recipes\u002Fecho-secret-enrollment",{"title":543,"path":544,"stem":545,"access":12},"Email archive","\u002Frecipes\u002Femail-archive","recipes\u002Femail-archive",{"title":547,"path":548,"stem":549,"access":12},"Email archive — threads & revisions","\u002Frecipes\u002Femail-archive-threads-revisions","recipes\u002Femail-archive-threads-revisions",{"title":551,"path":552,"stem":553,"access":12},"Export & portability","\u002Frecipes\u002Fexport-portability","recipes\u002Fexport-portability",{"title":555,"path":556,"stem":557,"access":12},"Passwordless OIDC (AWS Cognito)","\u002Frecipes\u002Fpasswordless-oidc","recipes\u002Fpasswordless-oidc",{"title":559,"path":560,"stem":561,"access":12},"Personal notebook","\u002Frecipes\u002Fpersonal-notebook","recipes\u002Fpersonal-notebook",{"title":563,"path":564,"stem":565,"access":12,"icon":566},"Playgrounds","\u002Frecipes\u002Fplaygrounds","recipes\u002Fplaygrounds","i-lucide-gamepad-2",{"title":568,"path":569,"stem":570,"access":12},"React invoice app","\u002Frecipes\u002Freact-invoices","recipes\u002Freact-invoices",{"title":572,"path":573,"stem":574,"access":12},"Collaborative app","\u002Frecipes\u002Frealtime-crdt-app","recipes\u002Frealtime-crdt-app",{"title":576,"path":577,"stem":578,"access":12,"icon":579},"Run the showcases","\u002Frecipes\u002Frun-the-showcases","recipes\u002Frun-the-showcases","i-lucide-flask-conical",{"title":581,"path":582,"stem":583,"access":12},"Search & RAG","\u002Frecipes\u002Fsearch-rag","recipes\u002Fsearch-rag",{"title":585,"path":586,"stem":587,"access":12},"Team vault topology","\u002Frecipes\u002Fteam-vault-topology","recipes\u002Fteam-vault-topology",{"title":589,"path":590,"stem":591,"access":12},"Unlock ceremonies","\u002Frecipes\u002Funlock-ceremonies","recipes\u002Funlock-ceremonies",{"title":593,"path":594,"stem":595,"access":12},"User preferences","\u002Frecipes\u002Fuser-preferences","recipes\u002Fuser-preferences",{"title":597,"path":598,"stem":599,"children":600},"Services","\u002Fservices","services",[601,604,608,612,616,620,624,628,632,636,640,644,648,652,656,660,664,668,672,676,680,684,688,692,696,700,704,710,714,718,722,726,730,734,738,742,746,750,755,759,763,767,771,775,779,783,787,791,795,799,803,807,811,815,819,823,827,831,835,839,843,847,851,855,859,863,867,871,875,879,883,887,891,895,899],{"title":10,"path":598,"stem":602,"access":12,"icon":603},"services\u002Findex","i-lucide-layers",{"title":605,"path":606,"stem":607,"access":12},"archive","\u002Fservices\u002Farchive","services\u002Farchive",{"title":609,"path":610,"stem":611,"access":12},"attestation","\u002Fservices\u002Fattestation","services\u002Fattestation",{"title":613,"path":614,"stem":615,"access":12},"auth-introspection","\u002Fservices\u002Fauth-introspection","services\u002Fauth-introspection",{"title":617,"path":618,"stem":619,"access":12},"auth-landscape","\u002Fservices\u002Fauth-landscape","services\u002Fauth-landscape",{"title":621,"path":622,"stem":623,"access":12},"blobs","\u002Fservices\u002Fblobs","services\u002Fblobs",{"title":625,"path":626,"stem":627,"access":12},"broker","\u002Fservices\u002Fbroker","services\u002Fbroker",{"title":629,"path":630,"stem":631,"access":12},"bundle","\u002Fservices\u002Fbundle","services\u002Fbundle",{"title":633,"path":634,"stem":635,"access":12},"classified","\u002Fservices\u002Fclassified","services\u002Fclassified",{"title":637,"path":638,"stem":639,"access":12},"computed","\u002Fservices\u002Fcomputed","services\u002Fcomputed",{"title":641,"path":642,"stem":643,"access":12},"consent","\u002Fservices\u002Fconsent","services\u002Fconsent",{"title":645,"path":646,"stem":647,"access":12},"cover","\u002Fservices\u002Fcover","services\u002Fcover",{"title":649,"path":650,"stem":651,"access":12},"coverage","\u002Fservices\u002Fcoverage","services\u002Fcoverage",{"title":653,"path":654,"stem":655,"access":12},"crdt","\u002Fservices\u002Fcrdt","services\u002Fcrdt",{"title":657,"path":658,"stem":659,"access":12},"cross-join","\u002Fservices\u002Fcross-join","services\u002Fcross-join",{"title":661,"path":662,"stem":663,"access":12},"custody","\u002Fservices\u002Fcustody","services\u002Fcustody",{"title":665,"path":666,"stem":667,"access":12},"derivations","\u002Fservices\u002Fderivations","services\u002Fderivations",{"title":669,"path":670,"stem":671,"access":12},"directory","\u002Fservices\u002Fdirectory","services\u002Fdirectory",{"title":673,"path":674,"stem":675,"access":12},"search — AI","\u002Fservices\u002Fembeddings","services\u002Fembeddings",{"title":677,"path":678,"stem":679,"access":12},"Field metadata","\u002Fservices\u002Ffield-metadata","services\u002Ffield-metadata",{"title":681,"path":682,"stem":683,"access":12},"Foreign refs","\u002Fservices\u002Fforeign-refs","services\u002Fforeign-refs",{"title":685,"path":686,"stem":687,"access":12},"forget","\u002Fservices\u002Fforget","services\u002Fforget",{"title":689,"path":690,"stem":691,"access":12},"governance","\u002Fservices\u002Fgovernance","services\u002Fgovernance",{"title":693,"path":694,"stem":695,"access":12},"guards","\u002Fservices\u002Fguards","services\u002Fguards",{"title":697,"path":698,"stem":699,"access":12},"history","\u002Fservices\u002Fhistory","services\u002Fhistory",{"title":701,"path":702,"stem":703,"access":12},"i18n","\u002Fservices\u002Fi18n","services\u002Fi18n",{"title":705,"path":706,"stem":707,"children":708,"access":12},"indexing","\u002Fservices\u002Findexing","services\u002Findexing",[709],{"title":705,"path":706,"stem":707,"access":12},{"title":711,"path":712,"stem":713,"access":12},"introspection","\u002Fservices\u002Fintrospection","services\u002Fintrospection",{"title":715,"path":716,"stem":717,"access":12},"joins","\u002Fservices\u002Fjoins","services\u002Fjoins",{"title":719,"path":720,"stem":721,"access":12},"lazy","\u002Fservices\u002Flazy","services\u002Flazy",{"title":723,"path":724,"stem":725,"access":12},"links","\u002Fservices\u002Flinks","services\u002Flinks",{"title":727,"path":728,"stem":729,"access":12},"live","\u002Fservices\u002Flive","services\u002Flive",{"title":731,"path":732,"stem":733,"access":12},"lookup","\u002Fservices\u002Flookup","services\u002Flookup",{"title":735,"path":736,"stem":737,"access":12},"manifest","\u002Fservices\u002Fmanifest","services\u002Fmanifest",{"title":739,"path":740,"stem":741,"access":12},"materialized-views","\u002Fservices\u002Fmaterialized-views","services\u002Fmaterialized-views",{"title":743,"path":744,"stem":745,"access":12},"Metadata ladder","\u002Fservices\u002Fmetadata-ladder","services\u002Fmetadata-ladder",{"title":747,"path":748,"stem":749,"access":12},"Metadata riders","\u002Fservices\u002Fmetadata-riders","services\u002Fmetadata-riders",{"title":751,"path":752,"stem":753,"access":12,"badge":754},"metrics","\u002Fservices\u002Fmetrics","services\u002Fmetrics","Planned",{"title":756,"path":757,"stem":758,"access":12,"badge":754},"migrations","\u002Fservices\u002Fmigrations","services\u002Fmigrations",{"title":760,"path":761,"stem":762,"access":12},"money","\u002Fservices\u002Fmoney","services\u002Fmoney",{"title":764,"path":765,"stem":766,"access":12},"numbering","\u002Fservices\u002Fnumbering","services\u002Fnumbering",{"title":768,"path":769,"stem":770,"access":12},"overlay-views","\u002Fservices\u002Foverlay-views","services\u002Foverlay-views",{"title":772,"path":773,"stem":774,"access":12,"badge":754},"partitioning","\u002Fservices\u002Fpartitioning","services\u002Fpartitioning",{"title":776,"path":777,"stem":778,"access":12},"periods","\u002Fservices\u002Fperiods","services\u002Fperiods",{"title":780,"path":781,"stem":782,"access":12},"persisted-schemas","\u002Fservices\u002Fpersisted-schemas","services\u002Fpersisted-schemas",{"title":784,"path":785,"stem":786,"access":12},"plaintext-bypass","\u002Fservices\u002Fplaintext-bypass","services\u002Fplaintext-bypass",{"title":788,"path":789,"stem":790,"access":12},"pod-redirect","\u002Fservices\u002Fpod-redirect","services\u002Fpod-redirect",{"title":792,"path":793,"stem":794,"access":12},"pod-signature","\u002Fservices\u002Fpod-signature","services\u002Fpod-signature",{"title":796,"path":797,"stem":798,"access":12},"policy","\u002Fservices\u002Fpolicy","services\u002Fpolicy",{"title":800,"path":801,"stem":802,"access":12},"portability","\u002Fservices\u002Fportability","services\u002Fportability",{"title":804,"path":805,"stem":806,"access":12},"reduce","\u002Fservices\u002Freduce","services\u002Freduce",{"title":808,"path":809,"stem":810,"access":12},"routing","\u002Fservices\u002Frouting","services\u002Frouting",{"title":812,"path":813,"stem":814,"access":12},"satellites","\u002Fservices\u002Fsatellites","services\u002Fsatellites",{"title":816,"path":817,"stem":818,"access":12},"schema-identifiers","\u002Fservices\u002Fschema-identifiers","services\u002Fschema-identifiers",{"title":820,"path":821,"stem":822,"access":12},"schema-update","\u002Fservices\u002Fschema-update","services\u002Fschema-update",{"title":824,"path":825,"stem":826,"access":12},"sealed-record","\u002Fservices\u002Fsealed-record","services\u002Fsealed-record",{"title":828,"path":829,"stem":830,"access":12},"sealing provider id","\u002Fservices\u002Fsealing-pid-stability","services\u002Fsealing-pid-stability",{"title":832,"path":833,"stem":834,"access":12},"search — full-text","\u002Fservices\u002Fsearch","services\u002Fsearch",{"title":836,"path":837,"stem":838,"access":12},"sequence","\u002Fservices\u002Fsequence","services\u002Fsequence",{"title":840,"path":841,"stem":842,"access":12},"session","\u002Fservices\u002Fsession","services\u002Fsession",{"title":844,"path":845,"stem":846,"access":12},"session-tiers","\u002Fservices\u002Fsession-tiers","services\u002Fsession-tiers",{"title":848,"path":849,"stem":850,"access":12},"shadow","\u002Fservices\u002Fshadow","services\u002Fshadow",{"title":852,"path":853,"stem":854,"access":12},"share-link","\u002Fservices\u002Fshare-link","services\u002Fshare-link",{"title":856,"path":857,"stem":858,"access":12},"snapshots","\u002Fservices\u002Fsnapshots","services\u002Fsnapshots",{"title":860,"path":861,"stem":862,"access":12},"store capabilities","\u002Fservices\u002Fstorage-capability-matrix","services\u002Fstorage-capability-matrix",{"title":864,"path":865,"stem":866,"access":12},"sync","\u002Fservices\u002Fsync","services\u002Fsync",{"title":868,"path":869,"stem":870,"access":12},"team","\u002Fservices\u002Fteam","services\u002Fteam",{"title":872,"path":873,"stem":874,"access":12},"tiers","\u002Fservices\u002Ftiers","services\u002Ftiers",{"title":876,"path":877,"stem":878,"access":12},"transactions","\u002Fservices\u002Ftransactions","services\u002Ftransactions",{"title":880,"path":881,"stem":882,"access":12},"partitions","\u002Fservices\u002Ftransferable-partitions","services\u002Ftransferable-partitions",{"title":884,"path":885,"stem":886,"access":12},"user-envelope","\u002Fservices\u002Fuser-envelope","services\u002Fuser-envelope",{"title":888,"path":889,"stem":890,"access":12,"badge":754},"validation","\u002Fservices\u002Fvalidation","services\u002Fvalidation",{"title":892,"path":893,"stem":894,"access":12},"vault-head","\u002Fservices\u002Fvault-head","services\u002Fvault-head",{"title":896,"path":897,"stem":898,"access":12},"via","\u002Fservices\u002Fvia","services\u002Fvia",{"title":900,"path":901,"stem":902,"access":12},"withdrawal","\u002Fservices\u002Fwithdrawal","services\u002Fwithdrawal",{"title":904,"path":905,"stem":906,"children":907},"Start","\u002Fstart","start",[908,911,915,919,923],{"title":10,"path":905,"stem":909,"access":12,"icon":910},"start\u002Findex","i-lucide-flag",{"title":912,"path":913,"stem":914,"access":12},"Install","\u002Fstart\u002Finstall","start\u002F1.install",{"title":916,"path":917,"stem":918,"access":12},"Your first vault","\u002Fstart\u002Ffirst-vault","start\u002F2.first-vault",{"title":920,"path":921,"stem":922,"access":12},"Your first service","\u002Fstart\u002Ffirst-service","start\u002F3.first-service",{"title":924,"path":925,"stem":926,"access":12},"See the ciphertext","\u002Fstart\u002Fsee-the-ciphertext","start\u002F4.see-the-ciphertext",{"id":928,"title":73,"access":12,"apiToc":929,"body":930,"category":3763,"description":3764,"extension":3765,"meta":3766,"navigation":3763,"nest":3767,"path":74,"seo":3768,"sinceVersion":3763,"status":3769,"stem":75,"subtitle":3763,"tier":3770,"tocExternal":3763,"__hash__":3771},"docs\u002Fcore\u002F2.noydb\u002F4.authentication.md",true,{"type":931,"value":932,"toc":3730},"minimark",[933,937,979,984,1010,1013,1058,1062,1069,1312,1323,1327,1334,1337,1341,1354,1436,1490,1494,1528,1532,1546,1553,1600,1611,1658,1664,1693,1699,1722,1728,1757,1770,1777,1783,1816,1834,1864,1870,1938,1961,1991,1997,2045,2060,2067,2073,2129,2143,2166,2173,2179,2205,2228,2262,2265,2276,2282,2311,2322,2347,2353,2406,2423,2439,2445,2460,2463,2470,2477,2491,2495,2511,2517,2523,2564,2567,2614,2623,2648,2663,2667,2677,2683,2928,2944,3372,3385,3471,3498,3501,3511,3517,3538,3541,3548,3554,3574,3581,3588,3594,3627,3633,3652,3658,3705,3713,3726],[934,935,73],"h1",{"id":936},"authentication",[938,939,940,941,945,946,950,951,950,954,957,958,961,962,965,966,969,970,973,974,978],"p",{},"The session-authentication ladder is ",[942,943,944],"strong",{},"strategy-free",". Unlike multi-user management (",[947,948,949],"code",{},"grant"," \u002F ",[947,952,953],{},"revoke",[947,955,956],{},"rotate",", which route through the opt-in team strategy and throw ",[947,959,960],{},"TeamNotEnabledError"," without it), every method below is always available on a plain ",[947,963,964],{},"createNoydb()"," session; the ones that touch a sensitive action are guarded by a ",[942,967,968],{},"policy gate",", not by a ",[947,971,972],{},"with*()"," opt-in. Recovery — regaining access when factors are lost — has moved to its own page: ",[975,976,77],"a",{"href":977},".\u002Frecovery",".",[980,981,983],"h2",{"id":982},"the-three-tiers","The three tiers",[938,985,986,987,990,991,994,995,1000,1001,1005,1006,978],{},"Every vault is unlocked with a ",[942,988,989],{},"tier-1"," secret; typing it on every read is not realistic, so noy-db layers two lighter-weight unlock methods on top of it and calls the resulting stack the ",[942,992,993],{},"three-tier privilege ladder",". The ladder concept, factor packages, policy-gate DSL, and worked flows live on ",[942,996,997],{},[975,998,844],{"href":999},"..\u002F..\u002Fservices\u002Fsession-tiers"," — this page is the kernel-API index for the methods that enroll and use each tier, plus a dedicated look at ",[975,1002,1004],{"href":1003},"#tier-1-the-root-secret","how tier 1 is supplied"," and at ",[975,1007,1009],{"href":1008},"#can-a-method-serve-a-different-tier","why a method cannot serve a different tier",[938,1011,1012],{},"Three concrete scenarios show the ladder in practice:",[1014,1015,1016,1031,1045],"ul",{},[1017,1018,1019,1022,1023,1026,1027,1030],"li",{},[942,1020,1021],{},"Daily password."," A SaaS user signs in each morning with a routine ",[942,1024,1025],{},"tier-2 password"," (",[947,1028,1029],{},"@noy-db\u002Fon-password",") — a second secret, distinct from the rarely-typed tier-1 phrase — which unwraps the DEK set directly.",[1017,1032,1033,1036,1037,1040,1041,1044],{},[942,1034,1035],{},"Biometric passkey."," A laptop user unlocks with a ",[942,1038,1039],{},"tier-2 passkey"," — Touch ID \u002F Face ID \u002F Windows Hello via ",[947,1042,1043],{},"@noy-db\u002Fon-webauthn"," — with no secret typed at all.",[1017,1046,1047,1050,1051,1026,1054,1057],{},[942,1048,1049],{},"PIN resume."," After a short idle window, the app resumes from a ",[942,1052,1053],{},"tier-3 PIN",[947,1055,1056],{},"@noy-db\u002Fon-pin",") over the DEKs still cached from the last unlock — it never re-derives the secret and cannot open a cold vault.",[980,1059,1061],{"id":1060},"the-three-tier-capability-matrix","The three-tier capability matrix",[938,1063,1064,1065,1068],{},"Each tier is a distinct cryptographic capability, not an interchangeable label. The full picture — use ",[942,1066,1067],{},"Expand"," for a large-screen view:",[1070,1071,1073],"wide-table",{"title":1072},"The three-tier ladder",[1074,1075,1076,1095],"table",{},[1077,1078,1079],"thead",{},[1080,1081,1082,1086,1089,1092],"tr",{},[1083,1084,1085],"th",{},"Capability \u002F property",[1083,1087,1088],{},"Tier 1 — root secret",[1083,1090,1091],{},"Tier 2 — authenticate",[1083,1093,1094],{},"Tier 3 — quick unlock",[1096,1097,1098,1115,1142,1166,1181,1200,1222,1238,1272,1296],"tbody",{},[1080,1099,1100,1106,1109,1112],{},[1101,1102,1103],"td",{},[942,1104,1105],{},"Opens a cold vault",[1101,1107,1108],{},"yes",[1101,1110,1111],{},"yes — any one enrolled slot",[1101,1113,1114],{},"no — resume only",[1080,1116,1117,1122,1125,1137],{},[1101,1118,1119],{},[942,1120,1121],{},"Session holds the KEK",[1101,1123,1124],{},"yes — derived from the secret (PBKDF2, 600k)",[1101,1126,1127,1128,1131,1132,950,1134,1136],{},"no — the unlock yields the DEK set, ",[947,1129,1130],{},"kek: null"," (even ",[947,1133,337],{},[947,1135,309],{}," wrap the DEKs, not the KEK)",[1101,1138,1139,1140],{},"no — ",[947,1141,1130],{},[1080,1143,1144,1150,1152,1163],{},[1101,1145,1146,1149],{},[942,1147,1148],{},"Can grant \u002F rotate \u002F enroll \u002F open another vault"," (KEK-requiring)",[1101,1151,1108],{},[1101,1153,1154,1155,1158,1159,1162],{},"no — blocked twice: no KEK, and ",[947,1156,1157],{},"activeTier"," 2 fails a ",[947,1160,1161],{},"minTier: 1"," gate",[1101,1164,1165],{},"no",[1080,1167,1168,1173,1175,1178],{},[1101,1169,1170],{},[942,1171,1172],{},"Can read \u002F write records",[1101,1174,1108],{},[1101,1176,1177],{},"yes — it holds the unwrapped DEK set",[1101,1179,1180],{},"yes — over the cached DEKs",[1080,1182,1183,1188,1191,1197],{},[1101,1184,1185],{},[942,1186,1187],{},"What its unlock yields",[1101,1189,1190],{},"the KEK, which unwraps the DEKs",[1101,1192,1193,1194,1196],{},"the DEK set directly (",[947,1195,1130],{},")",[1101,1198,1199],{},"the already-cached DEK map only",[1080,1201,1202,1207,1213,1219],{},[1101,1203,1204],{},[942,1205,1206],{},"Where the factor lives",[1101,1208,1209,1210],{},"user memory, or a managed ",[947,1211,1212],{},"NoydbSealer",[1101,1214,1215,1218],{},[947,1216,1217],{},"on-*"," slots inside the keyring file",[1101,1220,1221],{},"in-memory state, TTL-bounded",[1080,1223,1224,1229,1232,1235],{},[1101,1225,1226],{},[942,1227,1228],{},"Typical lifetime",[1101,1230,1231],{},"enrollment, recovery, tier-1-gated actions",[1101,1233,1234],{},"days–weeks (app-defined)",[1101,1236,1237],{},"minutes (app-defined)",[1080,1239,1240,1245,1256,1267],{},[1101,1241,1242],{},[942,1243,1244],{},"Package",[1101,1246,1247,1248,1251,1252,1255],{},"core ",[947,1249,1250],{},"@noy-db\u002Fhub"," — no ",[947,1253,1254],{},"on-"," package",[1101,1257,1258,950,1261,950,1264],{},[947,1259,1260],{},"on-password",[947,1262,1263],{},"on-webauthn",[947,1265,1266],{},"on-oidc",[1101,1268,1269],{},[947,1270,1271],{},"on-pin",[1080,1273,1274,1279,1287,1293],{},[1101,1275,1276],{},[942,1277,1278],{},"Survives secret rotation",[1101,1280,1281,1282,1286],{},"it ",[1283,1284,1285],"em",{},"is"," the secret",[1101,1288,1289,1290],{},"dropped unless preserved via ",[947,1291,1292],{},"slotCeremonies",[1101,1294,1295],{},"n\u002Fa — memory-only, expires on its TTL",[1080,1297,1298,1303,1306,1309],{},[1101,1299,1300],{},[942,1301,1302],{},"When it can't unlock, fall back to",[1101,1304,1305],{},"recovery (paper \u002F Shamir)",[1101,1307,1308],{},"another slot, or tier 1",[1101,1310,1311],{},"re-present tier 2",[938,1313,1314,1315,1318,1319,1322],{},"Higher tier outranks lower: only a higher tier can reset a lower one, and a policy gate's ",[947,1316,1317],{},"minTier"," is a ",[1283,1320,1321],{},"floor"," — a tier-1 session can always do what a tier-2 gate allows, never the reverse.",[980,1324,1326],{"id":1325},"the-on-method-family","The on-* method family",[938,1328,1329,1330,1333],{},"Every factor beyond the tier-1 secret ships as its own ",[947,1331,1332],{},"@noy-db\u002Fon-*"," package; the tier-1 secret itself is the one kernel-built credential. The whole catalog, by tier and integration level:",[1335,1336],"on-methods-table",{},[980,1338,1340],{"id":1339},"tier-1-the-root-secret","Tier 1 — the root secret",[938,1342,1343,1344,1347,1348,1350,1351,1353],{},"Tier 1 is the only credential that can open a ",[942,1345,1346],{},"cold"," vault — a fresh process with nothing cached. It establishes the session every lighter factor then re-opens, and it is built into ",[947,1349,1250],{}," core (there is no separate ",[947,1352,1217],{}," package for it). There are three ways to supply it:",[1014,1355,1356,1373,1410],{},[1017,1357,1358,1361,1362,1365,1366,1368,1369,1372],{},[942,1359,1360],{},"Owner secret (standard)."," Pass ",[947,1363,1364],{},"secret"," to ",[947,1367,964],{},"; the hub derives the KEK from it via PBKDF2-SHA256 (600,000 iterations) and unwraps the collection DEKs (see ",[975,1370,21],{"href":1371},".\u002Fenclave","). The secret lives only in the user's memory — the hub never stores it.",[1017,1374,1375,1378,1379,1382,1383,1385,1386,1389,1390,1397,1398,1401,1402,1405,1406,978],{},[942,1376,1377],{},"Self-generated sealed secret (managed mode)."," Set ",[947,1380,1381],{},"secretMode: 'managed'"," and supply a ",[947,1384,1212],{},": the hub mints a random 256-bit secret at first open and ",[1283,1387,1388],{},"seals"," it under a key your own infrastructure holds — an ",[975,1391,1393,1396],{"href":1392},".\u002Fenclave#the-sealing-key",[947,1394,1395],{},"at-*"," host"," such as an OS keychain or a cloud KMS — persisting only the sealed blob at ",[947,1399,1400],{},"_meta\u002Fsealed-secret",". The user never types or sees a secret, which makes the vault coercion-resistant: there is nothing to reveal. Managed mode requires a strong (Shamir) recovery profile and disables ",[947,1403,1404],{},"rotateSecret"," (the secret is replaced only through recovery under a fresh sealing key). Full flow: ",[975,1407,1409],{"href":1408},"..\u002F..\u002Fservices\u002Fsession-tiers#managed-secret-mode","session-tiers → managed mode",[1017,1411,1412,1419,1420,1422,1423,1426,1427,1429,1430,1432,1433,1435],{},[942,1413,1414,1415,1418],{},"Externally-supplied keyring (",[947,1416,1417],{},"getKeyring",")."," Skip the typed-secret model entirely: pass a ",[947,1421,1417],{}," callback that returns an already-unlocked keyring produced by WebAuthn, OIDC, or Shamir. This is how a ",[942,1424,1425],{},"passwordless app puts a tier-2 factor at the front door"," — the factor supplies the keyring at cold start, so no secret is ever typed. (",[947,1428,1364],{}," and ",[947,1431,1417],{}," are mutually exclusive; bootstrapping a brand-new vault still needs a secret or recovery code once, to enroll the first factor, after which you switch to ",[947,1434,1417],{},".)",[938,1437,1438,1441,1442,1445,1446,1449,1450,1453,1454,1457,1458,1429,1460,1463,1464,1467,1468,1471,1472,1475,1476,1429,1478,1481,1482,1485,1486,978],{},[942,1439,1440],{},"Secret strength is your choice; the tier is not."," The ",[1283,1443,1444],{},"tier"," of a factor is fixed by its cryptographic role (see ",[975,1447,1448],{"href":1008},"below","); the ",[1283,1451,1452],{},"strength"," of the tier-1 secret is not enforced by default. ",[947,1455,1456],{},"validateSecret"," is opt-in at ",[947,1459,964],{},[947,1461,1462],{},"grant()"," (default off), so ",[947,1465,1466],{},"secret: '1234'"," will open a vault and derive a real — if low-entropy — KEK. Pass ",[947,1469,1470],{},"validateSecret: true"," (or attach a ",[947,1473,1474],{},"SecretPolicy",") to enforce the phrase-format floor. ",[947,1477,1404],{},[947,1479,1480],{},"recoverSecret"," are the exception: they validate the new phrase by default, so opt out with ",[947,1483,1484],{},"allowWeakSecret"," if a weak one is deliberate. Format rules and worked examples: ",[975,1487,1489],{"href":1488},"..\u002F..\u002Fservices\u002Fsession-tiers#strength-validation","session-tiers → strength validation",[980,1491,1493],{"id":1492},"multi-owner-tier-1","Multi-owner tier 1",[938,1495,1496,1497,1500,1501,1504,1505,1508,1509,1512,1513,1516,1517,1519,1520,1523,1524,978],{},"A vault is not limited to a single root secret. Each user has their own ",[947,1498,1499],{},"_keyring\u002F\u003Cuser>"," record holding the ",[1283,1502,1503],{},"same"," collection DEKs wrapped under ",[1283,1506,1507],{},"their own"," KEK — so several people can each hold an independent tier-1 secret that unlocks the same vault, and more than one can hold the ",[947,1510,1511],{},"owner"," role (",[947,1514,1515],{},"grant(vault, { role: 'owner', … })","; owners cannot be revoked). This is the standard remedy for single-owner bus-factor risk: ",[947,1518,1462],{}," re-wraps the collection DEKs for the new user under a KEK derived from ",[1283,1521,1522],{},"their"," secret — see ",[975,1525,1527],{"href":1526},"..\u002F06-permissions-and-keyring","Permissions & keyring",[980,1529,1531],{"id":1530},"tier-2-authenticators","Tier 2 — authenticators",[938,1533,1534,1535,1538,1539,1541,1542,978],{},"Tier 2 is routine login — it replaces retyping the secret. It is ",[942,1536,1537],{},"multi-slot",": a user enrolls one or more authenticator slots, each independently wrapping the same KEK (or, for ",[947,1540,1260],{},", the DEK set directly), and any one enrolled slot unlocks the vault. Adding or removing a slot is a constant-time keyring write; it never re-keys the DEKs. Enroll \u002F remove \u002F update each check the corresponding policy gate. Full walkthrough: ",[975,1543,1545],{"href":1544},"..\u002F..\u002Fservices\u002Fsession-tiers#tier-2-authenticate-multi-slot","session-tiers → Tier 2",[1547,1548,1550],"h3",{"id":1549},"enrollauthenticator",[947,1551,1552],{},"enrollAuthenticator()",[1554,1555,1560],"pre",{"className":1556,"code":1557,"language":1558,"meta":1559,"style":1559},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","enrollAuthenticator(vault: string, options: EnrollAuthenticatorOptions, factors?: FactorProofBundle): Promise\u003Cvoid>\n","ts","",[947,1561,1562],{"__ignoreMap":1559},[1563,1564,1567,1571,1575,1579,1582,1584,1587,1590,1593,1597],"span",{"class":1565,"line":1566},"line",1,[1563,1568,1570],{"class":1569},"s2Zo4","enrollAuthenticator",[1563,1572,1574],{"class":1573},"sTEyZ","(vault: string",[1563,1576,1578],{"class":1577},"sMK4o",",",[1563,1580,1581],{"class":1573}," options: EnrollAuthenticatorOptions",[1563,1583,1578],{"class":1577},[1563,1585,1586],{"class":1573}," factors",[1563,1588,1589],{"class":1577},"?:",[1563,1591,1592],{"class":1573}," FactorProofBundle): ",[1563,1594,1596],{"class":1595},"sBMFI","Promise",[1563,1598,1599],{"class":1577},"\u003Cvoid>\n",[938,1601,1602,1603,1606,1607,1610],{},"Add a tier-2 authenticator slot to a vault's keyring. Takes the ",[942,1604,1605],{},"vault name",", not a keyring — the hub checks the ",[947,1608,1609],{},"enroll-authenticator"," gate and fetches the active keyring internally.",[1014,1612,1613,1619,1649],{},[1017,1614,1615,1618],{},[947,1616,1617],{},"vault"," — the vault whose keyring gains the slot.",[1017,1620,1621,1624,1625,1628,1629,1632,1633,1026,1636,950,1638,950,1640,1642,1643,1645,1646,978],{},[947,1622,1623],{},"options"," — an ",[947,1626,1627],{},"EnrollAuthenticatorOptions"," describing the slot: its caller-chosen ",[947,1630,1631],{},"id",", ",[947,1634,1635],{},"method",[947,1637,337],{},[947,1639,309],{},[947,1641,313],{},"), the wrap material produced by the matching ",[947,1644,1332],{}," package, and method-specific ",[947,1647,1648],{},"meta",[1017,1650,1651,1654,1655,1657],{},[947,1652,1653],{},"factors"," — factor proofs presented to satisfy the ",[947,1656,1609],{}," gate when a tightened policy demands them.",[1547,1659,1661],{"id":1660},"removeauthenticator",[947,1662,1663],{},"removeAuthenticator()",[1554,1665,1667],{"className":1556,"code":1666,"language":1558,"meta":1559,"style":1559},"removeAuthenticator(vault: string, slotId: string, factors?: FactorProofBundle): Promise\u003Cvoid>\n",[947,1668,1669],{"__ignoreMap":1559},[1563,1670,1671,1674,1676,1678,1681,1683,1685,1687,1689,1691],{"class":1565,"line":1566},[1563,1672,1673],{"class":1569},"removeAuthenticator",[1563,1675,1574],{"class":1573},[1563,1677,1578],{"class":1577},[1563,1679,1680],{"class":1573}," slotId: string",[1563,1682,1578],{"class":1577},[1563,1684,1586],{"class":1573},[1563,1686,1589],{"class":1577},[1563,1688,1592],{"class":1573},[1563,1690,1596],{"class":1595},[1563,1692,1599],{"class":1577},[938,1694,1695,1696,978],{},"Remove a tier-2 slot by id. Idempotent — removing a missing slot is a no-op. Gated by ",[947,1697,1698],{},"remove-authenticator",[1014,1700,1701,1706,1715],{},[1017,1702,1703,1705],{},[947,1704,1617],{}," — the vault whose keyring loses the slot.",[1017,1707,1708,1711,1712,1714],{},[947,1709,1710],{},"slotId"," — the ",[947,1713,1631],{}," of the slot to remove.",[1017,1716,1717,1654,1719,1721],{},[947,1718,1653],{},[947,1720,1698],{}," gate.",[1547,1723,1725],{"id":1724},"listauthenticators",[947,1726,1727],{},"listAuthenticators()",[1554,1729,1731],{"className":1556,"code":1730,"language":1558,"meta":1559,"style":1559},"listAuthenticators(vault: string): Promise\u003CReadonlyArray\u003CKeyringAuthenticator>>\n",[947,1732,1733],{"__ignoreMap":1559},[1563,1734,1735,1738,1741,1743,1746,1749,1751,1754],{"class":1565,"line":1566},[1563,1736,1737],{"class":1569},"listAuthenticators",[1563,1739,1740],{"class":1573},"(vault: string): ",[1563,1742,1596],{"class":1595},[1563,1744,1745],{"class":1577},"\u003C",[1563,1747,1748],{"class":1573},"ReadonlyArray",[1563,1750,1745],{"class":1577},[1563,1752,1753],{"class":1573},"KeyringAuthenticator",[1563,1755,1756],{"class":1577},">>\n",[938,1758,1759,1760,1762,1763,1632,1765,1767,1768,1418],{},"List the enrolled tier-2 slots on a vault's keyring. Each entry is a ",[947,1761,1753],{}," — a discriminated union of wrap-KEK slots (",[947,1764,337],{},[947,1766,309],{},") and wrap-DEKs slots (",[947,1769,313],{},[1014,1771,1772],{},[1017,1773,1774,1776],{},[947,1775,1617],{}," — the vault whose slots to list.",[1547,1778,1780],{"id":1779},"updateauthenticator",[947,1781,1782],{},"updateAuthenticator()",[1554,1784,1786],{"className":1556,"code":1785,"language":1558,"meta":1559,"style":1559},"updateAuthenticator(vault: string, slotId: string, options: UpdateAuthenticatorOptions, factors?: FactorProofBundle): Promise\u003Cvoid>\n",[947,1787,1788],{"__ignoreMap":1559},[1563,1789,1790,1793,1795,1797,1799,1801,1804,1806,1808,1810,1812,1814],{"class":1565,"line":1566},[1563,1791,1792],{"class":1569},"updateAuthenticator",[1563,1794,1574],{"class":1573},[1563,1796,1578],{"class":1577},[1563,1798,1680],{"class":1573},[1563,1800,1578],{"class":1577},[1563,1802,1803],{"class":1573}," options: UpdateAuthenticatorOptions",[1563,1805,1578],{"class":1577},[1563,1807,1586],{"class":1573},[1563,1809,1589],{"class":1577},[1563,1811,1592],{"class":1573},[1563,1813,1596],{"class":1595},[1563,1815,1599],{"class":1577},[938,1817,1818,1819,1821,1822,1632,1824,1826,1827,1830,1831,1833],{},"Rename or re-label a slot's ",[947,1820,1648],{}," — its ",[947,1823,1631],{},[947,1825,1635],{},", and wrap material are immutable. Gated by ",[947,1828,1829],{},"update-authenticator","; at least one ",[947,1832,1648],{}," field must be provided.",[1014,1835,1836,1841,1848,1858],{},[1017,1837,1838,1840],{},[947,1839,1617],{}," — the vault whose slot to update.",[1017,1842,1843,1711,1845,1847],{},[947,1844,1710],{},[947,1846,1631],{}," of the slot to relabel.",[1017,1849,1850,1624,1852,1855,1856,978],{},[947,1851,1623],{},[947,1853,1854],{},"UpdateAuthenticatorOptions"," carrying the replacement ",[947,1857,1648],{},[1017,1859,1860,1654,1862,1721],{},[947,1861,1653],{},[947,1863,1829],{},[1547,1865,1867],{"id":1866},"enrollwebauthn",[947,1868,1869],{},"enrollWebAuthn()",[1554,1871,1873],{"className":1556,"code":1872,"language":1558,"meta":1559,"style":1559},"enrollWebAuthn(vault: string, ceremony: (keyring: UnlockedKeyring) => Promise\u003CEnrollAuthenticatorOptions>, factors?: FactorProofBundle): Promise\u003C{ credentialId: string }>\n",[947,1874,1875],{"__ignoreMap":1559},[1563,1876,1877,1880,1882,1884,1887,1890,1894,1897,1900,1902,1906,1909,1911,1913,1916,1918,1920,1922,1924,1927,1930,1932,1935],{"class":1565,"line":1566},[1563,1878,1879],{"class":1569},"enrollWebAuthn",[1563,1881,1574],{"class":1573},[1563,1883,1578],{"class":1577},[1563,1885,1886],{"class":1573}," ceremony: ",[1563,1888,1889],{"class":1577},"(",[1563,1891,1893],{"class":1892},"sHdIc","keyring",[1563,1895,1896],{"class":1577},":",[1563,1898,1899],{"class":1595}," UnlockedKeyring",[1563,1901,1196],{"class":1577},[1563,1903,1905],{"class":1904},"spNyl"," =>",[1563,1907,1908],{"class":1595}," Promise",[1563,1910,1745],{"class":1577},[1563,1912,1627],{"class":1573},[1563,1914,1915],{"class":1577},">,",[1563,1917,1586],{"class":1573},[1563,1919,1589],{"class":1577},[1563,1921,1592],{"class":1573},[1563,1923,1596],{"class":1595},[1563,1925,1926],{"class":1577},"\u003C{",[1563,1928,1929],{"class":1595}," credentialId",[1563,1931,1896],{"class":1577},[1563,1933,1934],{"class":1573}," string",[1563,1936,1937],{"class":1577}," }>\n",[938,1939,1940,1941,1944,1945,1947,1948,1950,1951,1954,1955,1957,1958,1960],{},"Native-WebAuthn enrollment helper. Runs the caller's ",[947,1942,1943],{},"ceremony"," against the unlocked keyring to produce the slot options (whose ",[947,1946,1635],{}," must be ",[947,1949,337],{}," and whose ",[947,1952,1953],{},"meta.credentialId"," must be present), then persists the slot. Gated by ",[947,1956,1609],{}," like ",[947,1959,1552],{}," itself.",[1014,1962,1963,1968,1985],{},[1017,1964,1965,1967],{},[947,1966,1617],{}," — the vault whose keyring gains the WebAuthn slot.",[1017,1969,1970,1972,1973,1976,1977,1979,1980,1982,1983,978],{},[947,1971,1943],{}," — a callback receiving the ",[947,1974,1975],{},"UnlockedKeyring"," and returning ",[947,1978,1627],{},"; typically delegates to ",[947,1981,1869],{}," from ",[947,1984,1043],{},[1017,1986,1987,1654,1989,1721],{},[947,1988,1653],{},[947,1990,1609],{},[1547,1992,1994],{"id":1993},"listwebauthnslots",[947,1995,1996],{},"listWebAuthnSlots()",[1554,1998,2000],{"className":1556,"code":1999,"language":1558,"meta":1559,"style":1559},"listWebAuthnSlots(vault: string): Promise\u003CReadonlyArray\u003C{ id: string; enrolledAt: string; credentialId: string }>>\n",[947,2001,2002],{"__ignoreMap":1559},[1563,2003,2004,2007,2009,2011,2013,2015,2017,2020,2022,2024,2027,2030,2032,2034,2036,2038,2040,2042],{"class":1565,"line":1566},[1563,2005,2006],{"class":1569},"listWebAuthnSlots",[1563,2008,1740],{"class":1573},[1563,2010,1596],{"class":1595},[1563,2012,1745],{"class":1577},[1563,2014,1748],{"class":1573},[1563,2016,1926],{"class":1577},[1563,2018,2019],{"class":1595}," id",[1563,2021,1896],{"class":1577},[1563,2023,1934],{"class":1573},[1563,2025,2026],{"class":1577},";",[1563,2028,2029],{"class":1595}," enrolledAt",[1563,2031,1896],{"class":1577},[1563,2033,1934],{"class":1573},[1563,2035,2026],{"class":1577},[1563,2037,1929],{"class":1595},[1563,2039,1896],{"class":1577},[1563,2041,1934],{"class":1573},[1563,2043,2044],{"class":1577}," }>>\n",[938,2046,2047,2048,2050,2051,1632,2053,2056,2057,978],{},"List the enrolled slots scoped to the ",[947,2049,337],{}," method — each with its slot ",[947,2052,1631],{},[947,2054,2055],{},"enrolledAt"," timestamp, and ",[947,2058,2059],{},"credentialId",[1014,2061,2062],{},[1017,2063,2064,2066],{},[947,2065,1617],{}," — the vault whose WebAuthn slots to list.",[1547,2068,2070],{"id":2069},"unlockviaauthenticator",[947,2071,2072],{},"unlockViaAuthenticator()",[1554,2074,2076],{"className":1556,"code":2075,"language":1558,"meta":1559,"style":1559},"unlockViaAuthenticator(vault: string, slotId: string, verify: (slot: KeyringAuthenticator) => Promise\u003CUnlockedKeyring>): Promise\u003CUnlockedKeyring>\n",[947,2077,2078],{"__ignoreMap":1559},[1563,2079,2080,2083,2085,2087,2089,2091,2094,2096,2099,2101,2104,2106,2108,2110,2112,2114,2117,2120,2122,2124,2126],{"class":1565,"line":1566},[1563,2081,2082],{"class":1569},"unlockViaAuthenticator",[1563,2084,1574],{"class":1573},[1563,2086,1578],{"class":1577},[1563,2088,1680],{"class":1573},[1563,2090,1578],{"class":1577},[1563,2092,2093],{"class":1573}," verify: ",[1563,2095,1889],{"class":1577},[1563,2097,2098],{"class":1892},"slot",[1563,2100,1896],{"class":1577},[1563,2102,2103],{"class":1595}," KeyringAuthenticator",[1563,2105,1196],{"class":1577},[1563,2107,1905],{"class":1904},[1563,2109,1908],{"class":1595},[1563,2111,1745],{"class":1577},[1563,2113,1975],{"class":1573},[1563,2115,2116],{"class":1577},">",[1563,2118,2119],{"class":1573},"): ",[1563,2121,1596],{"class":1595},[1563,2123,1745],{"class":1577},[1563,2125,1975],{"class":1573},[1563,2127,2128],{"class":1577},">\n",[938,2130,2131,2132,2135,2136,2138,2139,2142],{},"Open a session via an enrolled slot. The ",[947,2133,2134],{},"verify"," callback receives the stored slot and returns the unlocked keyring — typically delegating to the matching ",[947,2137,1332],{}," package; subsequent ",[947,2140,2141],{},"checkGate()"," calls then see a tier-2 session.",[1014,2144,2145,2150,2157],{},[1017,2146,2147,2149],{},[947,2148,1617],{}," — the vault to unlock.",[1017,2151,2152,1711,2154,2156],{},[947,2153,1710],{},[947,2155,1631],{}," of the enrolled slot to unlock with.",[1017,2158,2159,1972,2161,2163,2164,978],{},[947,2160,2134],{},[947,2162,1753],{}," and returning the ",[947,2165,1975],{},[1547,2167,2169,2170,2172],{"id":2168},"tier-2-on-families","Tier-2 ",[947,2171,1217],{}," families",[938,2174,2175,2176,2178],{},"The wrap material for each slot comes from an ",[947,2177,1332],{}," package — a crypto primitive only; storage, rate-limiting, and UI belong to the caller. The three families that serve tier 2:",[1014,2180,2181,2189,2197],{},[1017,2182,2183,2188],{},[942,2184,2185],{},[975,2186,1260],{"href":2187},"..\u002F..\u002Ffamilies\u002Fon\u002Fpassword"," — a routine tier-2 login password, a separate secret from the tier-1 master phrase (PBKDF2-SHA256, wrap-DEKs slot).",[1017,2190,2191,2196],{},[942,2192,2193],{},[975,2194,1263],{"href":2195},"..\u002F..\u002Ffamilies\u002Fon\u002Fwebauthn"," — hardware-key \u002F platform-passkey unlock via WebAuthn (Touch ID, Face ID, Windows Hello, YubiKey); the tier-2 method with no knowledge factor.",[1017,2198,2199,2204],{},[942,2200,2201],{},[975,2202,1266],{"href":2203},"..\u002F..\u002Ffamilies\u002Fon\u002Foidc"," — split-key OIDC bridge (half the KEK on the device, half from the provider's key connector); requires operating a key-connector server.",[938,2206,2207,2212,2213,2216,2217,2220,2221,2223,2224,978],{},[942,2208,2209,2210,1418],{},"Federated trust (",[947,2211,1266],{}," When you unlock via OIDC, the provider — Google, Apple, LINE, Microsoft, Meta, AWS Cognito, any OIDC issuer — owns the ",[1283,2214,2215],{},"identity"," proof: the email-and-password, emailed-code, or biometric ceremony all happen at the provider, and noy-db only consumes the resulting ID token, so the provider's MFA strength flows into the tier-2 unlock for free. The provider does ",[942,2218,2219],{},"not"," own your key — ",[947,2222,1266],{}," XOR-splits the KEK into a device half (never leaves the device) and a server half (released after login), so a compromised provider still cannot decrypt. Full trust model: ",[975,2225,2227],{"href":2226},"..\u002F..\u002Ffamilies\u002Fon\u002Foidc#what-the-provider-is-responsible-for","on-oidc → what the provider is responsible for",[938,2229,2230,2231,2234,2235,1632,2238,1632,2241,1632,2244,2247,2248,2250,2251,2254,2255,978],{},"Not tier-2 authenticators, but sitting alongside the ladder: the ",[942,2232,2233],{},"step-up 2FA factors"," ",[947,2236,2237],{},"on-totp",[947,2239,2240],{},"on-email-otp",[947,2242,2243],{},"on-recovery",[947,2245,2246],{},"on-shamir",", and roaming ",[947,2249,1263],{}," supply fresh off-device proofs that policy gates can additionally demand (a fresh proof each time a gate asks); and ",[947,2252,2253],{},"on-magic-link"," is a delegated one-shot viewer session, not a session tier. See the ",[975,2256,2258,2261],{"href":2257},"..\u002F..\u002Ffamilies\u002Fon\u002F",[947,2259,2260],{},"on"," family catalog",[980,2263,1094],{"id":2264},"tier-3-quick-unlock",[938,2266,2267,2268,2271,2272,978],{},"Tier 3 is quick-resume after idle. It re-opens an ",[942,2269,2270],{},"already-unlocked"," session within a bounded idle window over the DEKs cached from a tier-1 or tier-2 unlock — it cannot open a cold vault, and on idle expiry the cache is wiped and tier 2 must be re-presented. It is never safe on a shared workstation, where the cached DEKs live on the device for the whole window. Full walkthrough: ",[975,2273,2275],{"href":2274},"..\u002F..\u002Fservices\u002Fsession-tiers#tier-3-unlock-quick-resume","session-tiers → Tier 3",[1547,2277,2279],{"id":2278},"enrollunlock",[947,2280,2281],{},"enrollUnlock()",[1554,2283,2285],{"className":1556,"code":2284,"language":1558,"meta":1559,"style":1559},"enrollUnlock(vault: string, state: QuickUnlockState, factors?: FactorProofBundle): Promise\u003Cvoid>\n",[947,2286,2287],{"__ignoreMap":1559},[1563,2288,2289,2292,2294,2296,2299,2301,2303,2305,2307,2309],{"class":1565,"line":1566},[1563,2290,2291],{"class":1569},"enrollUnlock",[1563,2293,1574],{"class":1573},[1563,2295,1578],{"class":1577},[1563,2297,2298],{"class":1573}," state: QuickUnlockState",[1563,2300,1578],{"class":1577},[1563,2302,1586],{"class":1573},[1563,2304,1589],{"class":1577},[1563,2306,1592],{"class":1573},[1563,2308,1596],{"class":1595},[1563,2310,1599],{"class":1577},[938,2312,2313,2314,2316,2317,1982,2320,1418],{},"Register a tier-3 quick-unlock state produced by an ",[947,2315,1217],{}," tier-3 primitive (e.g. ",[947,2318,2319],{},"enrollPin()",[947,2321,1056],{},[1014,2323,2324,2329,2338],{},[1017,2325,2326,2328],{},[947,2327,1617],{}," — the vault to register quick-unlock for.",[1017,2330,2331,1711,2334,2337],{},[947,2332,2333],{},"state",[947,2335,2336],{},"QuickUnlockState"," minted from an already-unlocked keyring.",[1017,2339,2340,2342,2343,2346],{},[947,2341,1653],{}," — factor proofs presented if the ",[947,2344,2345],{},"rotate-unlock"," gate demands them.",[1547,2348,2350],{"id":2349},"unlockviapin",[947,2351,2352],{},"unlockViaPin()",[1554,2354,2356],{"className":1556,"code":2355,"language":1558,"meta":1559,"style":1559},"unlockViaPin(vault: string, resume: (state: QuickUnlockState) => Promise\u003CUnlockedKeyring>): Promise\u003CUnlockedKeyring | undefined>\n",[947,2357,2358],{"__ignoreMap":1559},[1563,2359,2360,2363,2365,2367,2370,2372,2374,2376,2379,2381,2383,2385,2387,2389,2391,2393,2395,2397,2400,2403],{"class":1565,"line":1566},[1563,2361,2362],{"class":1569},"unlockViaPin",[1563,2364,1574],{"class":1573},[1563,2366,1578],{"class":1577},[1563,2368,2369],{"class":1573}," resume: ",[1563,2371,1889],{"class":1577},[1563,2373,2333],{"class":1892},[1563,2375,1896],{"class":1577},[1563,2377,2378],{"class":1595}," QuickUnlockState",[1563,2380,1196],{"class":1577},[1563,2382,1905],{"class":1904},[1563,2384,1908],{"class":1595},[1563,2386,1745],{"class":1577},[1563,2388,1975],{"class":1573},[1563,2390,2116],{"class":1577},[1563,2392,2119],{"class":1573},[1563,2394,1596],{"class":1595},[1563,2396,1745],{"class":1577},[1563,2398,2399],{"class":1573},"UnlockedKeyring ",[1563,2401,2402],{"class":1577},"|",[1563,2404,2405],{"class":1577}," undefined>\n",[938,2407,2408,2409,2412,2413,2416,2417,1982,2420,2422],{},"Resume a session via the registered tier-3 state. Resolves to ",[947,2410,2411],{},"undefined"," when no tier-3 state is registered for the vault; the ",[947,2414,2415],{},"resume"," callback typically delegates to ",[947,2418,2419],{},"resumePin()",[947,2421,1056],{},", which throws past its TTL \u002F attempt limit.",[1014,2424,2425,2430],{},[1017,2426,2427,2429],{},[947,2428,1617],{}," — the vault to resume.",[1017,2431,2432,2434,2435,2163,2437,978],{},[947,2433,2415],{}," — a callback receiving the stored ",[947,2436,2336],{},[947,2438,1975],{},[1547,2440,2442],{"id":2441},"clearquickunlock",[947,2443,2444],{},"clearQuickUnlock()",[1554,2446,2448],{"className":1556,"code":2447,"language":1558,"meta":1559,"style":1559},"clearQuickUnlock(vault: string): void\n",[947,2449,2450],{"__ignoreMap":1559},[1563,2451,2452,2455,2457],{"class":1565,"line":1566},[1563,2453,2454],{"class":1569},"clearQuickUnlock",[1563,2456,1740],{"class":1573},[1563,2458,2459],{"class":1577},"void\n",[938,2461,2462],{},"Synchronously drop the registered tier-3 quick-unlock state for a vault.",[1014,2464,2465],{},[1017,2466,2467,2469],{},[947,2468,1617],{}," — the vault whose quick-unlock state to clear.",[1547,2471,2473,2474,2476],{"id":2472},"tier-3-on-family","Tier-3 ",[947,2475,1217],{}," family",[1014,2478,2479],{},[1017,2480,2481,2486,2487,2490],{},[942,2482,2483],{},[975,2484,1271],{"href":2485},"..\u002F..\u002Ffamilies\u002Fon\u002Fpin"," — the canonical tier-3 primitive: a session-resume PIN (or biometric quick-lock) that re-unlocks cached DEKs without re-typing the secret. It ",[1283,2488,2489],{},"never"," replaces the secret; it only resumes an already-unlocked session.",[980,2492,2494],{"id":2493},"can-a-method-serve-a-different-tier","Can a method serve a different tier?",[938,2496,2497,2500,2501,2504,2505,2507,2508,2510],{},[942,2498,2499],{},"No — you cannot reassign a method's tier."," A factor's tier is pinned by what its unlock ",[1283,2502,2503],{},"yields",", not by any setting: tier 1 yields the KEK; tier 2 and tier 3 yield only the DEK set (",[947,2506,1130],{},"). You cannot promote ",[947,2509,1271],{}," into the cold-unlock primary — it holds no KEK, and its resume state must be minted from an already-unlocked session, so it structurally cannot open a cold vault.",[938,2512,2513,2516],{},[942,2514,2515],{},"But the tiers compose"," — a lighter factor can be the only thing a user ever presents, with a higher tier embedded behind it. Three shapes matter:",[938,2518,2519,2522],{},[942,2520,2521],{},"Authenticate with only a tier-2 method."," You can run a vault where no secret is typed at runtime, two ways:",[1014,2524,2525,2545],{},[1017,2526,2527,2531,2532,2535,2536,2538,2539,2541,2542,2544],{},[942,2528,2529],{},[947,2530,1417],{}," — pass a callback that returns an unlocked keyring from a WebAuthn \u002F OIDC ceremony. ",[947,2533,2534],{},"openVault"," treats this as a ",[942,2537,989],{}," session (most-privileged), so ",[947,2540,1317],{}," policy gates pass — but the keyring it returns still carries ",[947,2543,1130],{},", so KEK-requiring operations still cannot run.",[1017,2546,2547,1026,2550,2552,2553,2555,2556,2559,2560,2563],{},[942,2548,2549],{},"managed mode",[947,2551,1381],{}," + a ",[947,2554,1212],{},") — the hub self-generates a 256-bit secret and seals it under a key your infrastructure holds; at cold start the provider auto-unseals it, so the user types ",[942,2557,2558],{},"nothing"," and the session is a full ",[942,2561,2562],{},"tier 1"," with a real KEK.",[938,2565,2566],{},"Either way, bootstrapping the first enrollment needs a real secret or recovery code once; after that the factor (or the provider) is the only thing presented.",[938,2568,2569,2572,2573,2576,2577,950,2579,950,2581,2583,2584,2586,2587,2590,2591,2234,2594,2596,2597,2600,2601,2603,2604,2607,2608,2610,2611,2613],{},[942,2570,2571],{},"What a tier-2 session can and cannot do."," A tier-2 ",[1283,2574,2575],{},"authenticator"," unlock (",[947,2578,1260],{},[947,2580,1263],{},[947,2582,1266],{},") always returns ",[947,2585,1130],{}," — it hands you the DEK set, not the key that wraps it. So the session ",[942,2588,2589],{},"can"," read and write every collection it unwrapped, but ",[942,2592,2593],{},"cannot",[947,2595,949],{},", rotate the secret, enroll another authenticator, or open another vault: those need the KEK, and on an ",[947,2598,2599],{},"activeTier: 2"," session they are additionally denied by the ",[947,2602,1161],{}," policy gate. There is ",[942,2605,2606],{},"no session step-up API"," — to reach tier 1 you re-open with the real secret (or ",[947,2609,1417],{}," \u002F managed mode). This is why a machine job that must ",[947,2612,949],{}," or rotate runs under a real tier-1 secret (typically managed mode), never a tier-2 slot.",[938,2615,2616,2619,2620,2622],{},[942,2617,2618],{},"Pair a tier-3 PIN for fast resume."," Enroll ",[947,2621,1271],{}," after any unlock and the app resumes from the PIN within an idle window over the cached DEKs — a convenience layered on top of tier 1 or tier 2, never a replacement for either.",[938,2624,2625,2628,2629,2634,2635,2637,2638,2640,2641,2647],{},[942,2626,2627],{},"\"PIN-only\" apps — which lever you are actually pulling."," If you want the user to only ever type a short PIN, exactly one composition delivers it across cold starts: ",[942,2630,2631,2632,1960],{},"use the PIN as the tier-1 ",[947,2633,1364],{}," Validation is opt-in, so ",[947,2636,1466],{}," opens a vault and derives a real — if low-entropy — KEK; the same PIN then works for setup, cold unlock, and resume, because it ",[1283,2639,1285],{}," the master secret. Its low entropy becomes the vault's real strength floor, so pair it with your own rate-limiting or ",[975,2642,2644],{"href":2643},"..\u002F..\u002Ffamilies\u002Fon\u002Fthreat",[947,2645,2646],{},"on-threat"," lockout.",[938,2649,2650,2651,2653,2654,2656,2657,2659,2660,2662],{},"What you ",[942,2652,2593],{}," do is get \"only a PIN\" out of ",[947,2655,1271],{},": under managed mode the user types nothing at cold start (the provider unseals), and ",[947,2658,1271],{}," merely speeds a warm resume within a live session. So \"unlock with just a PIN\" is either a weak tier-1 secret (the PIN ",[1283,2661,1285],{}," the key) or managed mode (the user types nothing) — never the resume PIN acting as a cold primary.",[980,2664,2666],{"id":2665},"combining-methods-alternatives-and-2fa","Combining methods — alternatives and 2FA",[938,2668,2669,2670,2673,2674,978],{},"Two compositions get confused — one is ",[1283,2671,2672],{},"or",", the other is ",[1283,2675,2676],{},"and",[938,2678,2679,2682],{},[942,2680,2681],{},"Alternatives — any one unlocks (the multi-slot model)."," Enroll several tier-2 authenticators on one keyring; any single one opens the vault, so a user isn't locked out when they're away from one device. The slots are peers — adding or removing one is a constant-time keyring write that never re-keys the DEKs.",[1554,2684,2686],{"className":1556,"code":2685,"language":1558,"meta":1559,"style":1559},"\u002F\u002F Enroll two independent tier-2 slots on the same vault (wrap material comes from the on-* packages)\nawait db.team.enrollAuthenticator('acme', { id: 'passkey', method: 'webauthn', wrapped_kek, meta })\nawait db.team.enrollAuthenticator('acme', { id: 'work-pw', method: 'password', wrapped_deks, iv, meta })\n\n\u002F\u002F Unlock with EITHER — whichever the user has to hand:\nawait db.team.unlockViaAuthenticator('acme', 'passkey', verifyPasskey)   \u002F\u002F on the laptop\nawait db.team.unlockViaAuthenticator('acme', 'work-pw', verifyPassword)  \u002F\u002F or later, elsewhere\n",[947,2687,2688,2694,2770,2838,2844,2850,2889],{"__ignoreMap":1559},[1563,2689,2690],{"class":1565,"line":1566},[1563,2691,2693],{"class":2692},"sHwdD","\u002F\u002F Enroll two independent tier-2 slots on the same vault (wrap material comes from the on-* packages)\n",[1563,2695,2697,2701,2704,2706,2708,2710,2712,2714,2717,2721,2723,2725,2728,2731,2733,2736,2739,2741,2743,2746,2748,2750,2752,2754,2756,2759,2761,2764,2767],{"class":1565,"line":2696},2,[1563,2698,2700],{"class":2699},"s7zQu","await",[1563,2702,2703],{"class":1573}," db",[1563,2705,978],{"class":1577},[1563,2707,868],{"class":1573},[1563,2709,978],{"class":1577},[1563,2711,1570],{"class":1569},[1563,2713,1889],{"class":1573},[1563,2715,2716],{"class":1577},"'",[1563,2718,2720],{"class":2719},"sfazB","acme",[1563,2722,2716],{"class":1577},[1563,2724,1578],{"class":1577},[1563,2726,2727],{"class":1577}," {",[1563,2729,2019],{"class":2730},"swJcz",[1563,2732,1896],{"class":1577},[1563,2734,2735],{"class":1577}," '",[1563,2737,2738],{"class":2719},"passkey",[1563,2740,2716],{"class":1577},[1563,2742,1578],{"class":1577},[1563,2744,2745],{"class":2730}," method",[1563,2747,1896],{"class":1577},[1563,2749,2735],{"class":1577},[1563,2751,337],{"class":2719},[1563,2753,2716],{"class":1577},[1563,2755,1578],{"class":1577},[1563,2757,2758],{"class":1573}," wrapped_kek",[1563,2760,1578],{"class":1577},[1563,2762,2763],{"class":1573}," meta ",[1563,2765,2766],{"class":1577},"}",[1563,2768,2769],{"class":1573},")\n",[1563,2771,2773,2775,2777,2779,2781,2783,2785,2787,2789,2791,2793,2795,2797,2799,2801,2803,2806,2808,2810,2812,2814,2816,2818,2820,2822,2825,2827,2830,2832,2834,2836],{"class":1565,"line":2772},3,[1563,2774,2700],{"class":2699},[1563,2776,2703],{"class":1573},[1563,2778,978],{"class":1577},[1563,2780,868],{"class":1573},[1563,2782,978],{"class":1577},[1563,2784,1570],{"class":1569},[1563,2786,1889],{"class":1573},[1563,2788,2716],{"class":1577},[1563,2790,2720],{"class":2719},[1563,2792,2716],{"class":1577},[1563,2794,1578],{"class":1577},[1563,2796,2727],{"class":1577},[1563,2798,2019],{"class":2730},[1563,2800,1896],{"class":1577},[1563,2802,2735],{"class":1577},[1563,2804,2805],{"class":2719},"work-pw",[1563,2807,2716],{"class":1577},[1563,2809,1578],{"class":1577},[1563,2811,2745],{"class":2730},[1563,2813,1896],{"class":1577},[1563,2815,2735],{"class":1577},[1563,2817,313],{"class":2719},[1563,2819,2716],{"class":1577},[1563,2821,1578],{"class":1577},[1563,2823,2824],{"class":1573}," wrapped_deks",[1563,2826,1578],{"class":1577},[1563,2828,2829],{"class":1573}," iv",[1563,2831,1578],{"class":1577},[1563,2833,2763],{"class":1573},[1563,2835,2766],{"class":1577},[1563,2837,2769],{"class":1573},[1563,2839,2841],{"class":1565,"line":2840},4,[1563,2842,2843],{"emptyLinePlaceholder":929},"\n",[1563,2845,2847],{"class":1565,"line":2846},5,[1563,2848,2849],{"class":2692},"\u002F\u002F Unlock with EITHER — whichever the user has to hand:\n",[1563,2851,2853,2855,2857,2859,2861,2863,2865,2867,2869,2871,2873,2875,2877,2879,2881,2883,2886],{"class":1565,"line":2852},6,[1563,2854,2700],{"class":2699},[1563,2856,2703],{"class":1573},[1563,2858,978],{"class":1577},[1563,2860,868],{"class":1573},[1563,2862,978],{"class":1577},[1563,2864,2082],{"class":1569},[1563,2866,1889],{"class":1573},[1563,2868,2716],{"class":1577},[1563,2870,2720],{"class":2719},[1563,2872,2716],{"class":1577},[1563,2874,1578],{"class":1577},[1563,2876,2735],{"class":1577},[1563,2878,2738],{"class":2719},[1563,2880,2716],{"class":1577},[1563,2882,1578],{"class":1577},[1563,2884,2885],{"class":1573}," verifyPasskey)   ",[1563,2887,2888],{"class":2692},"\u002F\u002F on the laptop\n",[1563,2890,2892,2894,2896,2898,2900,2902,2904,2906,2908,2910,2912,2914,2916,2918,2920,2922,2925],{"class":1565,"line":2891},7,[1563,2893,2700],{"class":2699},[1563,2895,2703],{"class":1573},[1563,2897,978],{"class":1577},[1563,2899,868],{"class":1573},[1563,2901,978],{"class":1577},[1563,2903,2082],{"class":1569},[1563,2905,1889],{"class":1573},[1563,2907,2716],{"class":1577},[1563,2909,2720],{"class":2719},[1563,2911,2716],{"class":1577},[1563,2913,1578],{"class":1577},[1563,2915,2735],{"class":1577},[1563,2917,2805],{"class":2719},[1563,2919,2716],{"class":1577},[1563,2921,1578],{"class":1577},[1563,2923,2924],{"class":1573}," verifyPassword)  ",[1563,2926,2927],{"class":2692},"\u002F\u002F or later, elsewhere\n",[938,2929,2930,2933,2934,2936,2937,2940,2941,2943],{},[942,2931,2932],{},"Two factors together — 2FA (the policy gate)."," The unlock is one factor; a ",[942,2935,968],{}," demands a ",[1283,2938,2939],{},"second, fresh"," factor before a sensitive action. This is the ",[1283,2942,2676],{},": unlock with your passkey (something you have), then prove a TOTP code (something on your phone) before the vault will export.",[1554,2945,2947],{"className":1556,"code":2946,"language":1558,"meta":1559,"style":1559},"import { createNoydb, PERSONAL_POLICY, PolicyDeniedError } from '@noy-db\u002Fhub'\n\nconst db = await createNoydb({\n  store, user: 'alice', secret,\n  policy: {\n    ...PERSONAL_POLICY,\n    gates: {\n      ...PERSONAL_POLICY.gates,\n      \u002F\u002F exporting plaintext now needs a tier-2 session PLUS a fresh TOTP proof\n      'export-plaintext': { minTier: 2, factors: [{ anyOf: ['totp'], freshnessMs: 5 * 60_000 }] },\n    },\n  },\n})\n\n\u002F\u002F …unlock (tier 2) as usual, then present the second factor at the sensitive action:\ntry {\n  await db.checkGate('acme', 'export-plaintext', {\n    factors: [{ kind: 'totp', payload: { code: '123456' }, mintedAt: new Date().toISOString() }],\n  })\n  \u002F\u002F …run the export\n} catch (e) {\n  if (e instanceof PolicyDeniedError) {\n    \u002F\u002F e.reason: 'insufficient-tier' | 'missing-factor' | 'stale-proof' | …\n  }\n}\n",[947,2948,2949,2982,2986,3007,3034,3044,3054,3063,3078,3084,3160,3166,3172,3179,3184,3190,3198,3231,3306,3314,3320,3333,3354,3360,3366],{"__ignoreMap":1559},[1563,2950,2951,2954,2956,2959,2961,2964,2966,2969,2972,2975,2977,2979],{"class":1565,"line":1566},[1563,2952,2953],{"class":2699},"import",[1563,2955,2727],{"class":1577},[1563,2957,2958],{"class":1573}," createNoydb",[1563,2960,1578],{"class":1577},[1563,2962,2963],{"class":1573}," PERSONAL_POLICY",[1563,2965,1578],{"class":1577},[1563,2967,2968],{"class":1573}," PolicyDeniedError",[1563,2970,2971],{"class":1577}," }",[1563,2973,2974],{"class":2699}," from",[1563,2976,2735],{"class":1577},[1563,2978,1250],{"class":2719},[1563,2980,2981],{"class":1577},"'\n",[1563,2983,2984],{"class":1565,"line":2696},[1563,2985,2843],{"emptyLinePlaceholder":929},[1563,2987,2988,2991,2994,2997,3000,3002,3004],{"class":1565,"line":2772},[1563,2989,2990],{"class":1904},"const",[1563,2992,2993],{"class":1573}," db ",[1563,2995,2996],{"class":1577},"=",[1563,2998,2999],{"class":2699}," await",[1563,3001,2958],{"class":1569},[1563,3003,1889],{"class":1573},[1563,3005,3006],{"class":1577},"{\n",[1563,3008,3009,3012,3014,3017,3019,3021,3024,3026,3028,3031],{"class":1565,"line":2840},[1563,3010,3011],{"class":1573},"  store",[1563,3013,1578],{"class":1577},[1563,3015,3016],{"class":2730}," user",[1563,3018,1896],{"class":1577},[1563,3020,2735],{"class":1577},[1563,3022,3023],{"class":2719},"alice",[1563,3025,2716],{"class":1577},[1563,3027,1578],{"class":1577},[1563,3029,3030],{"class":1573}," secret",[1563,3032,3033],{"class":1577},",\n",[1563,3035,3036,3039,3041],{"class":1565,"line":2846},[1563,3037,3038],{"class":2730},"  policy",[1563,3040,1896],{"class":1577},[1563,3042,3043],{"class":1577}," {\n",[1563,3045,3046,3049,3052],{"class":1565,"line":2852},[1563,3047,3048],{"class":1577},"    ...",[1563,3050,3051],{"class":1573},"PERSONAL_POLICY",[1563,3053,3033],{"class":1577},[1563,3055,3056,3059,3061],{"class":1565,"line":2891},[1563,3057,3058],{"class":2730},"    gates",[1563,3060,1896],{"class":1577},[1563,3062,3043],{"class":1577},[1563,3064,3066,3069,3071,3073,3076],{"class":1565,"line":3065},8,[1563,3067,3068],{"class":1577},"      ...",[1563,3070,3051],{"class":1573},[1563,3072,978],{"class":1577},[1563,3074,3075],{"class":1573},"gates",[1563,3077,3033],{"class":1577},[1563,3079,3081],{"class":1565,"line":3080},9,[1563,3082,3083],{"class":2692},"      \u002F\u002F exporting plaintext now needs a tier-2 session PLUS a fresh TOTP proof\n",[1563,3085,3087,3090,3093,3095,3097,3099,3102,3104,3108,3110,3112,3114,3117,3120,3123,3125,3127,3129,3131,3133,3136,3138,3141,3143,3146,3149,3152,3154,3157],{"class":1565,"line":3086},10,[1563,3088,3089],{"class":1577},"      '",[1563,3091,3092],{"class":2730},"export-plaintext",[1563,3094,2716],{"class":1577},[1563,3096,1896],{"class":1577},[1563,3098,2727],{"class":1577},[1563,3100,3101],{"class":2730}," minTier",[1563,3103,1896],{"class":1577},[1563,3105,3107],{"class":3106},"sbssI"," 2",[1563,3109,1578],{"class":1577},[1563,3111,1586],{"class":2730},[1563,3113,1896],{"class":1577},[1563,3115,3116],{"class":1573}," [",[1563,3118,3119],{"class":1577},"{",[1563,3121,3122],{"class":2730}," anyOf",[1563,3124,1896],{"class":1577},[1563,3126,3116],{"class":1573},[1563,3128,2716],{"class":1577},[1563,3130,333],{"class":2719},[1563,3132,2716],{"class":1577},[1563,3134,3135],{"class":1573},"]",[1563,3137,1578],{"class":1577},[1563,3139,3140],{"class":2730}," freshnessMs",[1563,3142,1896],{"class":1577},[1563,3144,3145],{"class":3106}," 5",[1563,3147,3148],{"class":1577}," *",[1563,3150,3151],{"class":3106}," 60_000",[1563,3153,2971],{"class":1577},[1563,3155,3156],{"class":1573},"] ",[1563,3158,3159],{"class":1577},"},\n",[1563,3161,3163],{"class":1565,"line":3162},11,[1563,3164,3165],{"class":1577},"    },\n",[1563,3167,3169],{"class":1565,"line":3168},12,[1563,3170,3171],{"class":1577},"  },\n",[1563,3173,3175,3177],{"class":1565,"line":3174},13,[1563,3176,2766],{"class":1577},[1563,3178,2769],{"class":1573},[1563,3180,3182],{"class":1565,"line":3181},14,[1563,3183,2843],{"emptyLinePlaceholder":929},[1563,3185,3187],{"class":1565,"line":3186},15,[1563,3188,3189],{"class":2692},"\u002F\u002F …unlock (tier 2) as usual, then present the second factor at the sensitive action:\n",[1563,3191,3193,3196],{"class":1565,"line":3192},16,[1563,3194,3195],{"class":2699},"try",[1563,3197,3043],{"class":1577},[1563,3199,3201,3204,3206,3208,3211,3213,3215,3217,3219,3221,3223,3225,3227,3229],{"class":1565,"line":3200},17,[1563,3202,3203],{"class":2699},"  await",[1563,3205,2703],{"class":1573},[1563,3207,978],{"class":1577},[1563,3209,3210],{"class":1569},"checkGate",[1563,3212,1889],{"class":2730},[1563,3214,2716],{"class":1577},[1563,3216,2720],{"class":2719},[1563,3218,2716],{"class":1577},[1563,3220,1578],{"class":1577},[1563,3222,2735],{"class":1577},[1563,3224,3092],{"class":2719},[1563,3226,2716],{"class":1577},[1563,3228,1578],{"class":1577},[1563,3230,3043],{"class":1577},[1563,3232,3234,3237,3239,3241,3243,3246,3248,3250,3252,3254,3256,3259,3261,3263,3266,3268,3270,3273,3275,3278,3281,3283,3286,3289,3292,3294,3297,3300,3302,3304],{"class":1565,"line":3233},18,[1563,3235,3236],{"class":2730},"    factors",[1563,3238,1896],{"class":1577},[1563,3240,3116],{"class":2730},[1563,3242,3119],{"class":1577},[1563,3244,3245],{"class":2730}," kind",[1563,3247,1896],{"class":1577},[1563,3249,2735],{"class":1577},[1563,3251,333],{"class":2719},[1563,3253,2716],{"class":1577},[1563,3255,1578],{"class":1577},[1563,3257,3258],{"class":2730}," payload",[1563,3260,1896],{"class":1577},[1563,3262,2727],{"class":1577},[1563,3264,3265],{"class":2730}," code",[1563,3267,1896],{"class":1577},[1563,3269,2735],{"class":1577},[1563,3271,3272],{"class":2719},"123456",[1563,3274,2716],{"class":1577},[1563,3276,3277],{"class":1577}," },",[1563,3279,3280],{"class":2730}," mintedAt",[1563,3282,1896],{"class":1577},[1563,3284,3285],{"class":1577}," new",[1563,3287,3288],{"class":1569}," Date",[1563,3290,3291],{"class":2730},"()",[1563,3293,978],{"class":1577},[1563,3295,3296],{"class":1569},"toISOString",[1563,3298,3299],{"class":2730},"() ",[1563,3301,2766],{"class":1577},[1563,3303,3135],{"class":2730},[1563,3305,3033],{"class":1577},[1563,3307,3309,3312],{"class":1565,"line":3308},19,[1563,3310,3311],{"class":1577},"  }",[1563,3313,2769],{"class":2730},[1563,3315,3317],{"class":1565,"line":3316},20,[1563,3318,3319],{"class":2692},"  \u002F\u002F …run the export\n",[1563,3321,3323,3325,3328,3331],{"class":1565,"line":3322},21,[1563,3324,2766],{"class":1577},[1563,3326,3327],{"class":2699}," catch",[1563,3329,3330],{"class":1573}," (e) ",[1563,3332,3006],{"class":1577},[1563,3334,3336,3339,3341,3344,3347,3349,3352],{"class":1565,"line":3335},22,[1563,3337,3338],{"class":2699},"  if",[1563,3340,1026],{"class":2730},[1563,3342,3343],{"class":1573},"e",[1563,3345,3346],{"class":1577}," instanceof",[1563,3348,2968],{"class":1595},[1563,3350,3351],{"class":2730},") ",[1563,3353,3006],{"class":1577},[1563,3355,3357],{"class":1565,"line":3356},23,[1563,3358,3359],{"class":2692},"    \u002F\u002F e.reason: 'insufficient-tier' | 'missing-factor' | 'stale-proof' | …\n",[1563,3361,3363],{"class":1565,"line":3362},24,[1563,3364,3365],{"class":1577},"  }\n",[1563,3367,3369],{"class":1565,"line":3368},25,[1563,3370,3371],{"class":1577},"}\n",[938,3373,3374,3380,3381,3384],{},[942,3375,3376,3377,1586],{},"Require two ",[1283,3378,3379],{},"distinct"," (true 2-of-N) — set ",[947,3382,3383],{},"count"," on the requirement:",[1554,3386,3388],{"className":1556,"code":3387,"language":1558,"meta":1559,"style":1559},"'rotate-secret': { minTier: 1, factors: [{ anyOf: ['totp', 'email-otp', 'recovery'], count: 2 }] }\n\u002F\u002F the gate now needs TWO different factors from the list, each freshly proven\n",[947,3389,3390,3466],{"__ignoreMap":1559},[1563,3391,3392,3394,3397,3399,3402,3404,3406,3408,3411,3413,3415,3417,3419,3421,3423,3425,3427,3429,3431,3433,3435,3437,3439,3441,3443,3445,3447,3449,3451,3453,3456,3458,3460,3462,3464],{"class":1565,"line":1566},[1563,3393,2716],{"class":1577},[1563,3395,3396],{"class":2719},"rotate-secret",[1563,3398,2716],{"class":1577},[1563,3400,3401],{"class":1573},": ",[1563,3403,3119],{"class":1577},[1563,3405,3101],{"class":2730},[1563,3407,1896],{"class":1577},[1563,3409,3410],{"class":3106}," 1",[1563,3412,1578],{"class":1577},[1563,3414,1586],{"class":2730},[1563,3416,1896],{"class":1577},[1563,3418,3116],{"class":1573},[1563,3420,3119],{"class":1577},[1563,3422,3122],{"class":2730},[1563,3424,1896],{"class":1577},[1563,3426,3116],{"class":1573},[1563,3428,2716],{"class":1577},[1563,3430,333],{"class":2719},[1563,3432,2716],{"class":1577},[1563,3434,1578],{"class":1577},[1563,3436,2735],{"class":1577},[1563,3438,301],{"class":2719},[1563,3440,2716],{"class":1577},[1563,3442,1578],{"class":1577},[1563,3444,2735],{"class":1577},[1563,3446,321],{"class":2719},[1563,3448,2716],{"class":1577},[1563,3450,3135],{"class":1573},[1563,3452,1578],{"class":1577},[1563,3454,3455],{"class":2730}," count",[1563,3457,1896],{"class":1577},[1563,3459,3107],{"class":3106},[1563,3461,2971],{"class":1577},[1563,3463,3156],{"class":1573},[1563,3465,3371],{"class":1577},[1563,3467,3468],{"class":1565,"line":2696},[1563,3469,3470],{"class":2692},"\u002F\u002F the gate now needs TWO different factors from the list, each freshly proven\n",[938,3472,3473,3474,3486,3487,3489,3490,3493,3494,978],{},"The mental model: ",[942,3475,3476,3477,3479,3480,3482,3483,3485],{},"alternatives (",[1283,3478,2672],{},") are multiple tier-2 slots; combined 2FA (",[1283,3481,2676],{},") is a policy gate's ",[947,3484,1653],{}," requirement layered on the unlock."," A gate can demand ",[947,3488,3383],{}," distinct factors within a ",[947,3491,3492],{},"freshnessMs"," window; the full DSL, factor kinds, and shipped presets live on ",[975,3495,3497],{"href":3496},"..\u002F..\u002Fservices\u002Fsession-tiers#policy-gates","session-tiers → policy gates",[980,3499,3500],{"id":613},"Auth introspection",[938,3502,3503,3504,3507,3508,978],{},"Read-only views of a vault's auth setup: a plain-English summary, a Mermaid diagram of the tier model, and per-user (or bulk) enrollment summaries. The two vault-wide surfaces are ungated; the per-user surfaces are guarded by the ",[947,3505,3506],{},"view-user-auth"," gate (disabled by default) and pass their output through a strict field allowlist. Full treatment: ",[975,3509,613],{"href":3510},"..\u002F..\u002Fservices\u002Fauth-introspection",[1547,3512,3514],{"id":3513},"describeauthconfig",[947,3515,3516],{},"describeAuthConfig()",[1554,3518,3520],{"className":1556,"code":3519,"language":1558,"meta":1559,"style":1559},"describeAuthConfig(vault: string): Promise\u003Cstring>\n",[947,3521,3522],{"__ignoreMap":1559},[1563,3523,3524,3527,3529,3531,3533,3536],{"class":1565,"line":1566},[1563,3525,3526],{"class":1569},"describeAuthConfig",[1563,3528,1740],{"class":1573},[1563,3530,1596],{"class":1595},[1563,3532,1745],{"class":1577},[1563,3534,3535],{"class":1573},"string",[1563,3537,2128],{"class":1577},[938,3539,3540],{},"A plain-English summary of the vault's auth configuration — enrolled tiers, slots, and recovery profiles. Ungated.",[1014,3542,3543],{},[1017,3544,3545,3547],{},[947,3546,1617],{}," — the vault to describe.",[1547,3549,3551],{"id":3550},"diagramauthconfig",[947,3552,3553],{},"diagramAuthConfig()",[1554,3555,3557],{"className":1556,"code":3556,"language":1558,"meta":1559,"style":1559},"diagramAuthConfig(vault: string): Promise\u003Cstring>\n",[947,3558,3559],{"__ignoreMap":1559},[1563,3560,3561,3564,3566,3568,3570,3572],{"class":1565,"line":1566},[1563,3562,3563],{"class":1569},"diagramAuthConfig",[1563,3565,1740],{"class":1573},[1563,3567,1596],{"class":1595},[1563,3569,1745],{"class":1577},[1563,3571,3535],{"class":1573},[1563,3573,2128],{"class":1577},[938,3575,3576,3577,3580],{},"A Mermaid ",[947,3578,3579],{},"flowchart TB"," of the vault's tier model, for UI rendering. Ungated.",[1014,3582,3583],{},[1017,3584,3585,3587],{},[947,3586,1617],{}," — the vault to diagram.",[1547,3589,3591],{"id":3590},"describeuserauth",[947,3592,3593],{},"describeUserAuth()",[1554,3595,3597],{"className":1556,"code":3596,"language":1558,"meta":1559,"style":1559},"describeUserAuth(vault: string, userId: string, factors?: FactorProofBundle): Promise\u003Cstring>\n",[947,3598,3599],{"__ignoreMap":1559},[1563,3600,3601,3604,3606,3608,3611,3613,3615,3617,3619,3621,3623,3625],{"class":1565,"line":1566},[1563,3602,3603],{"class":1569},"describeUserAuth",[1563,3605,1574],{"class":1573},[1563,3607,1578],{"class":1577},[1563,3609,3610],{"class":1573}," userId: string",[1563,3612,1578],{"class":1577},[1563,3614,1586],{"class":1573},[1563,3616,1589],{"class":1577},[1563,3618,1592],{"class":1573},[1563,3620,1596],{"class":1595},[1563,3622,1745],{"class":1577},[1563,3624,3535],{"class":1573},[1563,3626,2128],{"class":1577},[938,3628,3629,3630,3632],{},"A per-user enrollment summary, passed through a strict field allowlist. Guarded by the ",[947,3631,3506],{}," gate (disabled by default).",[1014,3634,3635,3640,3646],{},[1017,3636,3637,3639],{},[947,3638,1617],{}," — the vault the user belongs to.",[1017,3641,3642,3645],{},[947,3643,3644],{},"userId"," — the principal whose auth to describe.",[1017,3647,3648,1654,3650,1721],{},[947,3649,1653],{},[947,3651,3506],{},[1547,3653,3655],{"id":3654},"describeallusersauth",[947,3656,3657],{},"describeAllUsersAuth()",[1554,3659,3661],{"className":1556,"code":3660,"language":1558,"meta":1559,"style":1559},"describeAllUsersAuth(vault: string, factors?: FactorProofBundle): Promise\u003CArray\u003C{ userId: string; description: string }>>\n",[947,3662,3663],{"__ignoreMap":1559},[1563,3664,3665,3668,3670,3672,3674,3676,3678,3680,3682,3685,3687,3690,3692,3694,3696,3699,3701,3703],{"class":1565,"line":1566},[1563,3666,3667],{"class":1569},"describeAllUsersAuth",[1563,3669,1574],{"class":1573},[1563,3671,1578],{"class":1577},[1563,3673,1586],{"class":1573},[1563,3675,1589],{"class":1577},[1563,3677,1592],{"class":1573},[1563,3679,1596],{"class":1595},[1563,3681,1745],{"class":1577},[1563,3683,3684],{"class":1573},"Array",[1563,3686,1926],{"class":1577},[1563,3688,3689],{"class":1595}," userId",[1563,3691,1896],{"class":1577},[1563,3693,1934],{"class":1573},[1563,3695,2026],{"class":1577},[1563,3697,3698],{"class":1595}," description",[1563,3700,1896],{"class":1577},[1563,3702,1934],{"class":1573},[1563,3704,2044],{"class":1577},[938,3706,3707,3708,3710,3711,1721],{},"The bulk variant of ",[947,3709,3603],{}," — one allowlisted description per user. Guarded by the ",[947,3712,3506],{},[1014,3714,3715,3720],{},[1017,3716,3717,3719],{},[947,3718,1617],{}," — the vault whose users to describe.",[1017,3721,3722,1654,3724,1721],{},[947,3723,1653],{},[947,3725,3506],{},[3727,3728,3729],"style",{},"html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":1559,"searchDepth":2772,"depth":2772,"links":3731},[3732,3733,3734,3735,3736,3737,3748,3755,3756,3757],{"id":982,"depth":2696,"text":983},{"id":1060,"depth":2696,"text":1061},{"id":1325,"depth":2696,"text":1326},{"id":1339,"depth":2696,"text":1340},{"id":1492,"depth":2696,"text":1493},{"id":1530,"depth":2696,"text":1531,"children":3738},[3739,3740,3741,3742,3743,3744,3745,3746],{"id":1549,"depth":2772,"text":1552},{"id":1660,"depth":2772,"text":1663},{"id":1724,"depth":2772,"text":1727},{"id":1779,"depth":2772,"text":1782},{"id":1866,"depth":2772,"text":1869},{"id":1993,"depth":2772,"text":1996},{"id":2069,"depth":2772,"text":2072},{"id":2168,"depth":2772,"text":3747},"Tier-2 on-* families",{"id":2264,"depth":2696,"text":1094,"children":3749},[3750,3751,3752,3753],{"id":2278,"depth":2772,"text":2281},{"id":2349,"depth":2772,"text":2352},{"id":2441,"depth":2772,"text":2444},{"id":2472,"depth":2772,"text":3754},"Tier-3 on-* family",{"id":2493,"depth":2696,"text":2494},{"id":2665,"depth":2696,"text":2666},{"id":613,"depth":2696,"text":3500,"children":3758},[3759,3760,3761,3762],{"id":3513,"depth":2772,"text":3516},{"id":3550,"depth":2772,"text":3553},{"id":3590,"depth":2772,"text":3593},{"id":3654,"depth":2772,"text":3657},null,"The strategy-free session-auth ladder: tier 1 (secret \u002F getKeyring), tier-2 authenticators and on-* families, tier-3 quick-unlock, and auth introspection.","md",{},"kernel",{"title":73,"description":3764},"stable","essential","2UzuYLsMWZeDywZW3pxXRJbinK87EqIWg2pO4UODPX8",{"data":3773,"body":3774},{},{"type":3775,"children":3776},"root",[3777],{"type":3778,"tag":938,"props":3779,"children":3780},"element",{},[3781,3784,3789,3791,3796,3798,3803,3805,3810,3812,3817],{"type":3782,"value":3783},"text","Factor — ",{"type":3778,"tag":942,"props":3785,"children":3786},{},[3787],{"type":3782,"value":3788},"Knowledge",{"type":3782,"value":3790}," (something you remember) · ",{"type":3778,"tag":942,"props":3792,"children":3793},{},[3794],{"type":3782,"value":3795},"Possession",{"type":3782,"value":3797}," (a device you hold) · ",{"type":3778,"tag":942,"props":3799,"children":3800},{},[3801],{"type":3782,"value":3802},"Biometric",{"type":3782,"value":3804}," (something you are) · ",{"type":3778,"tag":942,"props":3806,"children":3807},{},[3808],{"type":3782,"value":3809},"Provider-set",{"type":3782,"value":3811}," (chosen by the OIDC issuer) · ",{"type":3778,"tag":942,"props":3813,"children":3814},{},[3815],{"type":3782,"value":3816},"—",{"type":3782,"value":3818}," not a factor.",1791896579907]