diff --git a/AGENTS.md b/AGENTS.md
index 0c703c2..6e547ca 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,19 +1,34 @@
# AGENTS.md — Auth-Yes System Guidelines & Operating Protocol
## 1. Project Context
-Auth-Yes is a standalone, ultra-low-friction, zero-trust Identity and Access Management (IAM) fabric and WebAuthn Passkey authority.
+
+Auth-Yes is a standalone, ultra-low-friction, zero-trust Identity and Access
+Management (IAM) fabric and WebAuthn Passkey authority.
+
- **Runtime:** Deno 2.x (TypeScript 5.x)
-- **Architecture:** Modular Deno Workspace (`sdk/`, `server/`, `ui/`, `spire_ffi/`, `infra/`)
+- **Architecture:** Modular Deno Workspace (`sdk/`, `server/`, `ui/`,
+ `spire_ffi/`, `infra/`)
- **Web API & SSR:** Hono with pure Hono SSR JSX (Strictly React-free)
-- **Workload Mesh:** ConnectRPC daemon + Rust SPIFFE/mTLS FFI crate (`spire_ffi/`)
-- **Data Layer:** Dedicated PostgreSQL 18 + Valkey 8 (L1/L2 RESP3 Client Tracking)
-- **Cookie Scope:** Wildcard `.atyg.org` domain scoping with host-collision sweep
+- **Workload Mesh:** ConnectRPC daemon + Rust SPIFFE/mTLS FFI crate
+ (`spire_ffi/`)
+- **Data Layer:** Dedicated PostgreSQL 18 + Valkey 8 (L1/L2 RESP3 Client
+ Tracking)
+- **Cookie Scope:** Wildcard `.atyg.org` domain scoping with host-collision
+ sweep
## 2. Key Architecture Standards
-1. **Zero-Dependency SDK:** `@auth-yes/sdk` must remain 100% free of backend/database imports. ConnectRPC contracts live in `sdk/gen/`.
-2. **Security:** Session invalidation and revocation MUST always be handled server-side (`deleteCookie` across host and wildcard domains).
-3. **Quality Gates:** Every PR must pass `deno fmt`, `deno task lint`, `deno task check`, and `deno test`.
+
+1. **Zero-Dependency SDK:** `@auth-yes/sdk` must remain 100% free of
+ backend/database imports. ConnectRPC contracts live in `sdk/gen/`.
+2. **Security:** Session invalidation and revocation MUST always be handled
+ server-side (`deleteCookie` across host and wildcard domains).
+3. **Quality Gates:** Every PR must pass `deno fmt`, `deno task lint`,
+ `deno task check`, and `deno test`.
## 3. History & Context Link
+
This repository was cleanly extracted from `ed-droid`.
-- **Reference Conversation:** `conversation://6a3fa402-ae0a-4231-9991-b0ff79a61e0f`
+
+- **Reference Conversation:**
+ [Auth-Yes Genesis Transcript](conversation://6a3fa402-ae0a-4231-9991-b0ff79a61e0f)
+ (`conversation://6a3fa402-ae0a-4231-9991-b0ff79a61e0f`)
diff --git a/LICENSE b/LICENSE
index 41e1857..b6ffe2a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,8 @@
-MIT License
+Auth-Yes is dual-licensed under both the MIT License and the Apache License (Version 2.0).
-Copyright (c) 2026 Tyler Gillispie
+You may select, at your option, either:
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+- The MIT License ([LICENSE-MIT](LICENSE-MIT))
+- The Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+SPDX-License-Identifier: MIT OR Apache-2.0
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..ba07c8f
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2026 Tyler Gillispie
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..41e1857
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 Tyler Gillispie
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index f40b8a4..db7c06d 100644
--- a/README.md
+++ b/README.md
@@ -453,3 +453,14 @@ latency.
| **Phase 2** | **Zero-Trust App Mesh (Backend)** | - ConnectRPC / gRPC transport
- SPIFFE/SPIRE mTLS client certificate validation
- Default-deny RBAC grant verification
- ForwardAuth `/api/forward-auth` endpoint | **COMPLETED** |
| **Phase 3** | **Admin Console UI Views (Current)** | - `/admin/apps` Application Registry UI
- `/admin/invites` Multi-Type Token Provisioning UI
- `/admin/users/:id` App RBAC Grant Manager UI
- Domain wildcard cookie (`.atyg.org`) deployment | **READY FOR BUILD** |
| **Phase 4** | **Edge Hardening & Future Scoping** | - Traefik Tier 1 global ForwardAuth fallback configuration
- Traefik Tier 2 ForwardAuth container routing
- Related Origin Requests (`/.well-known/webauthn`) for external TLDs | **FUTURE** |
+
+---
+
+## 8. License
+
+Auth-Yes is dual-licensed under:
+
+- **MIT License** ([LICENSE-MIT](LICENSE-MIT))
+- **Apache License, Version 2.0** ([LICENSE-APACHE](LICENSE-APACHE))
+
+`SPDX-License-Identifier: MIT OR Apache-2.0`
diff --git a/deno.json b/deno.json
index c8eecdb..35e2505 100644
--- a/deno.json
+++ b/deno.json
@@ -4,6 +4,7 @@
"./server",
"./ui"
],
+ "license": "MIT OR Apache-2.0",
"tasks": {
"lint": "deno lint",
"fmt": "deno fmt",
diff --git a/deno.lock b/deno.lock
new file mode 100644
index 0000000..ec51e8a
--- /dev/null
+++ b/deno.lock
@@ -0,0 +1,391 @@
+{
+ "version": "5",
+ "specifiers": {
+ "jsr:@cliffy/ansi@1.0.0-rc.7": "1.0.0-rc.7",
+ "jsr:@cliffy/command@1.0.0-rc.7": "1.0.0-rc.7",
+ "jsr:@cliffy/flags@1.0.0-rc.7": "1.0.0-rc.7",
+ "jsr:@cliffy/internal@1.0.0-rc.7": "1.0.0-rc.7",
+ "jsr:@cliffy/keycode@1.0.0-rc.7": "1.0.0-rc.7",
+ "jsr:@cliffy/prompt@1.0.0-rc.7": "1.0.0-rc.7",
+ "jsr:@cliffy/table@1.0.0-rc.7": "1.0.0-rc.7",
+ "jsr:@hono/hono@4": "4.12.23",
+ "jsr:@simplewebauthn/server@13": "13.3.2",
+ "jsr:@std/assert@*": "1.0.19",
+ "jsr:@std/assert@0.226": "0.226.0",
+ "jsr:@std/assert@~1.0.6": "1.0.19",
+ "jsr:@std/encoding@1": "1.0.10",
+ "jsr:@std/encoding@~1.0.5": "1.0.10",
+ "jsr:@std/fmt@0.225.2": "0.225.2",
+ "jsr:@std/fmt@~1.0.2": "1.0.8",
+ "jsr:@std/internal@^1.0.12": "1.0.14",
+ "jsr:@std/io@~0.224.9": "0.224.9",
+ "jsr:@std/path@0.225.2": "0.225.2",
+ "jsr:@std/path@~1.0.6": "1.0.9",
+ "jsr:@std/text@~1.0.7": "1.0.19",
+ "npm:@bufbuild/protobuf@^1.10.0": "1.10.1",
+ "npm:@connectrpc/connect-node@^1.4.0": "1.7.0_@bufbuild+protobuf@1.10.1_@connectrpc+connect@1.7.0__@bufbuild+protobuf@1.10.1",
+ "npm:@connectrpc/connect@^1.4.0": "1.7.0_@bufbuild+protobuf@1.10.1",
+ "npm:@hexagon/base64@^1.1.27": "1.1.28",
+ "npm:@levischuck/tiny-cbor@~0.2.2": "0.2.11",
+ "npm:@peculiar/asn1-android@^2.6.0": "2.9.4",
+ "npm:@peculiar/asn1-ecc@^2.6.1": "2.9.4",
+ "npm:@peculiar/asn1-rsa@^2.6.1": "2.9.4",
+ "npm:@peculiar/asn1-schema@*": "2.9.4",
+ "npm:@peculiar/asn1-schema@^2.6.0": "2.9.4",
+ "npm:@peculiar/asn1-x509@*": "2.9.4",
+ "npm:@peculiar/asn1-x509@^2.6.1": "2.9.4",
+ "npm:@peculiar/x509@*": "1.14.3",
+ "npm:@peculiar/x509@^1.14.3": "1.14.3",
+ "npm:ioredis@*": "6.0.0",
+ "npm:postgres@3": "3.4.9"
+ },
+ "jsr": {
+ "@cliffy/ansi@1.0.0-rc.7": {
+ "integrity": "f71c921cce224c13d322e5cedba4f38e8f7354c7d855c9cb22729362a53f25aa",
+ "dependencies": [
+ "jsr:@cliffy/internal",
+ "jsr:@std/encoding@~1.0.5",
+ "jsr:@std/io"
+ ]
+ },
+ "@cliffy/command@1.0.0-rc.7": {
+ "integrity": "1288808d7a3cd18b86c24c2f920e47a6d954b7e23cadc35c8cbd78f8be41f0cd",
+ "dependencies": [
+ "jsr:@cliffy/flags",
+ "jsr:@cliffy/internal",
+ "jsr:@cliffy/table",
+ "jsr:@std/fmt@~1.0.2",
+ "jsr:@std/text"
+ ]
+ },
+ "@cliffy/flags@1.0.0-rc.7": {
+ "integrity": "318d9be98f6a6417b108e03dec427dea96cdd41a15beb21d2554ae6da450a781",
+ "dependencies": [
+ "jsr:@std/text"
+ ]
+ },
+ "@cliffy/internal@1.0.0-rc.7": {
+ "integrity": "10412636ab3e67517d448be9eaab1b70c88eba9be22617b5d146257a11cc9b17"
+ },
+ "@cliffy/keycode@1.0.0-rc.7": {
+ "integrity": "5b3f6c33994e81a76b79f108b1989642ac22705840da33781f7972d7dff05503"
+ },
+ "@cliffy/prompt@1.0.0-rc.7": {
+ "integrity": "a9cbd13acd8073558447cae8ca4cf593c09d23bcbe429cc63346920c21187b83",
+ "dependencies": [
+ "jsr:@cliffy/ansi",
+ "jsr:@cliffy/internal",
+ "jsr:@cliffy/keycode",
+ "jsr:@std/assert@~1.0.6",
+ "jsr:@std/fmt@~1.0.2",
+ "jsr:@std/io",
+ "jsr:@std/path@~1.0.6",
+ "jsr:@std/text"
+ ]
+ },
+ "@cliffy/table@1.0.0-rc.7": {
+ "integrity": "9fdd9776eda28a0b397981c400eeb1aa36da2371b43eefe12e6ff555290e3180",
+ "dependencies": [
+ "jsr:@std/fmt@~1.0.2"
+ ]
+ },
+ "@hono/hono@4.12.23": {
+ "integrity": "9d9f3da498f69c311b5f92d973eb3b8ebc973b5fd2b4972781b556e07818a745"
+ },
+ "@simplewebauthn/server@13.3.2": {
+ "integrity": "296795949df2f73be2d3f858a7fc6c9ff4eaa42a85a1d1e3c6ab7c1b20d8a57a",
+ "dependencies": [
+ "npm:@hexagon/base64",
+ "npm:@levischuck/tiny-cbor",
+ "npm:@peculiar/asn1-android",
+ "npm:@peculiar/asn1-ecc",
+ "npm:@peculiar/asn1-rsa",
+ "npm:@peculiar/asn1-schema@^2.6.0",
+ "npm:@peculiar/asn1-x509@^2.6.1",
+ "npm:@peculiar/x509@^1.14.3"
+ ]
+ },
+ "@std/assert@0.226.0": {
+ "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3"
+ },
+ "@std/assert@1.0.19": {
+ "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e",
+ "dependencies": [
+ "jsr:@std/internal"
+ ]
+ },
+ "@std/encoding@1.0.10": {
+ "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1"
+ },
+ "@std/fmt@0.225.2": {
+ "integrity": "8a2d157586372f9d5e74cdf0f463a828dee5d09d7de10e56394d8f20dbb5bf26"
+ },
+ "@std/fmt@1.0.8": {
+ "integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7"
+ },
+ "@std/internal@1.0.14": {
+ "integrity": "291516b3d4c35024d6ffbc0a9df5bf4c64116e05b50012cf846710152d2ffdf7"
+ },
+ "@std/io@0.224.9": {
+ "integrity": "4414664b6926f665102e73c969cfda06d2c4c59bd5d0c603fd4f1b1c840d6ee3"
+ },
+ "@std/path@0.225.2": {
+ "integrity": "0f2db41d36b50ef048dcb0399aac720a5348638dd3cb5bf80685bf2a745aa506",
+ "dependencies": [
+ "jsr:@std/assert@0.226"
+ ]
+ },
+ "@std/path@1.0.9": {
+ "integrity": "260a49f11edd3db93dd38350bf9cd1b4d1366afa98e81b86167b4e3dd750129e"
+ },
+ "@std/text@1.0.19": {
+ "integrity": "003a0e032d360e8c3a4e0410fb792c77a66bd6553fee9d60c6ec1bce30d29223"
+ }
+ },
+ "npm": {
+ "@bufbuild/protobuf@1.10.1": {
+ "integrity": "sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ=="
+ },
+ "@connectrpc/connect-node@1.7.0_@bufbuild+protobuf@1.10.1_@connectrpc+connect@1.7.0__@bufbuild+protobuf@1.10.1": {
+ "integrity": "sha512-6vaPIkG/NyhxlYgytLoR9KYbPhczEboFB2OYWkA9qvUz1K7efXfeGrlRxoLtpa+r8VxyIOw73w5ktNe743nD+A==",
+ "dependencies": [
+ "@bufbuild/protobuf",
+ "@connectrpc/connect",
+ "undici"
+ ]
+ },
+ "@connectrpc/connect@1.7.0_@bufbuild+protobuf@1.10.1": {
+ "integrity": "sha512-iNKdJRi69YP3mq6AePRT8F/HrxWCewrhxnLMNm0vpqXAR8biwzRtO6Hjx80C6UvtKJ5sFmffQT7I4Baecz389w==",
+ "dependencies": [
+ "@bufbuild/protobuf"
+ ]
+ },
+ "@fastify/busboy@2.1.1": {
+ "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="
+ },
+ "@hexagon/base64@1.1.28": {
+ "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw=="
+ },
+ "@ioredis/commands@2.0.0": {
+ "integrity": "sha512-vrx0AE/T0h7cRZwfo1M39Cr+ZhZrkf0V8mQN75wucKCxCLD9l/VX6no3gFvrLqD1IlG/1LtzWovqEw3t0Vr9zg=="
+ },
+ "@levischuck/tiny-cbor@0.2.11": {
+ "integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow=="
+ },
+ "@peculiar/asn1-android@2.9.4": {
+ "integrity": "sha512-SYHm4SoWSI0nRCoos6jpGusIqhPH9bbGBqv7ohlZ+H6BunrDzzQPk2ePgDuEUzV82OdvbLgtW4twUDwhU9P3YQ==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-cms@2.9.4": {
+ "integrity": "sha512-cben7oxmQsUGZqotus7yt0srYdncOT6RNWcTQ77T2RFOXejYVYkXadrfePdRcrVpO9K95IRLKKglG2k38jKXuw==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "@peculiar/asn1-x509-attr",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-csr@2.9.4": {
+ "integrity": "sha512-xd4YN4vpRjkDAQWVfZZkeu12IEND7DOpkqaHSIHxZl1uggUNa9Ju0QxY2jHvDAS9pP0zhRBytg8ifsnGo3V0jw==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-ecc@2.9.4": {
+ "integrity": "sha512-JJXefFshRAuVAjWQo/39bkg1ywc1VaiO44S8RRC+Ykvf/u2KDmYffoDb0ZBPCR5uJy4AGKQhl8mX+Q8ShcWaXQ==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-pfx@2.9.4": {
+ "integrity": "sha512-khuGzHTzNzk4GDlIBEILyIs6Lce0yn0ZBdoI9v93kmNncfZRhD+AQ5ODFqdhvoE8cMJF/JMTQ8yA+t1D14kqCw==",
+ "dependencies": [
+ "@peculiar/asn1-cms",
+ "@peculiar/asn1-pkcs8",
+ "@peculiar/asn1-rsa",
+ "@peculiar/asn1-schema",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-pkcs8@2.9.4": {
+ "integrity": "sha512-duRdotlUx9eDZe6QrQpQKl61RbWykCHBCkKayP8V8XdEFwlKHZ8qGGDMyS6Pye7OX7nLFttTTpRkJeet78ckwQ==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-pkcs9@2.9.4": {
+ "integrity": "sha512-kaL4cNxBpdQE2dKlyZBqz4ygCrwffO+8wfoxTEqM1Z8RadvCeELBRzcv0dzM8aY9azHMwODO5nxU65zXmhToOQ==",
+ "dependencies": [
+ "@peculiar/asn1-cms",
+ "@peculiar/asn1-pfx",
+ "@peculiar/asn1-pkcs8",
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "@peculiar/asn1-x509-attr",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-rsa@2.9.4": {
+ "integrity": "sha512-pZ96eD1PptovcWQ/GSmuNFXd/7EQJNlKfDaNCyE2rx3W0v6QFelkzquVqRSRyyDXXCYD69ZXJDzZ8GhIiQzKoA==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-schema@2.9.4": {
+ "integrity": "sha512-GjzePcT9Iw8NzeOPf73iNS9xM+TBhd/FilAfP+RQGkTMQJTVWtytN3JHJACCjf/ABNau5S7mS3g+DcuxmRgYEg==",
+ "dependencies": [
+ "@peculiar/utils",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-x509-attr@2.9.4": {
+ "integrity": "sha512-ehQXbpQaQYycgu8OrvigwSPTFfVRcu0ECNYCWw+yzBp02Lw5paRqzzhUpfOgO2K38+WfFZuEz/0RPtam5g0OMg==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/asn1-x509@2.9.4": {
+ "integrity": "sha512-CxhBo/RdEbMMob7T31ZdQjGuoyRFLVwrDzTn25bihzBasRg9kRm/0IxIPvhgQtcK/9dNcO1XQL2fuPugwELL0Q==",
+ "dependencies": [
+ "@peculiar/asn1-schema",
+ "@peculiar/utils",
+ "asn1js",
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/utils@2.0.3": {
+ "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==",
+ "dependencies": [
+ "tslib@2.8.1"
+ ]
+ },
+ "@peculiar/x509@1.14.3": {
+ "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==",
+ "dependencies": [
+ "@peculiar/asn1-cms",
+ "@peculiar/asn1-csr",
+ "@peculiar/asn1-ecc",
+ "@peculiar/asn1-pkcs9",
+ "@peculiar/asn1-rsa",
+ "@peculiar/asn1-schema",
+ "@peculiar/asn1-x509",
+ "pvtsutils",
+ "reflect-metadata",
+ "tslib@2.8.1",
+ "tsyringe"
+ ]
+ },
+ "asn1js@3.0.10": {
+ "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==",
+ "dependencies": [
+ "pvtsutils",
+ "pvutils",
+ "tslib@2.8.1"
+ ]
+ },
+ "cluster-key-slot@1.1.1": {
+ "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw=="
+ },
+ "debug@4.4.3": {
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dependencies": [
+ "ms"
+ ]
+ },
+ "denque@2.1.0": {
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
+ },
+ "ioredis@6.0.0": {
+ "integrity": "sha512-f+Dtubxfpf6KYFq7WVXJoOLn0bk4TJrMrN9SzeE+jrWrCWj7XX3fA6vkryafhADX+GMymRxgDJDOI33COkJc0w==",
+ "dependencies": [
+ "@ioredis/commands",
+ "cluster-key-slot",
+ "debug",
+ "denque",
+ "redis-errors",
+ "standard-as-callback"
+ ]
+ },
+ "ms@2.1.3": {
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "postgres@3.4.9": {
+ "integrity": "sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw=="
+ },
+ "pvtsutils@1.3.6": {
+ "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==",
+ "dependencies": [
+ "tslib@2.8.1"
+ ]
+ },
+ "pvutils@1.2.0": {
+ "integrity": "sha512-BbubeCEyTuQjVMakvJQ/Sxbc93F2pwmbsxONT/ZRrwU7Ua38d8unYTwXpTVLAKJ4BDuH9IGztCjQcd/N/39Dvg=="
+ },
+ "redis-errors@1.2.0": {
+ "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="
+ },
+ "reflect-metadata@0.2.2": {
+ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="
+ },
+ "standard-as-callback@2.1.0": {
+ "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
+ },
+ "tslib@1.14.1": {
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "tslib@2.8.1": {
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "tsyringe@4.10.0": {
+ "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==",
+ "dependencies": [
+ "tslib@1.14.1"
+ ]
+ },
+ "undici@5.29.0": {
+ "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
+ "dependencies": [
+ "@fastify/busboy"
+ ]
+ }
+ },
+ "workspace": {
+ "dependencies": [
+ "jsr:@cliffy/command@1.0.0-rc.7",
+ "jsr:@hono/hono@4",
+ "npm:@bufbuild/protobuf@^1.10.0",
+ "npm:@connectrpc/connect-node@^1.4.0",
+ "npm:@connectrpc/connect@^1.4.0"
+ ],
+ "members": {
+ "ui": {
+ "dependencies": [
+ "jsr:@hono/hono@4"
+ ]
+ }
+ }
+ }
+}
diff --git a/sdk/deno.json b/sdk/deno.json
index 95c7acb..f4e4aa5 100644
--- a/sdk/deno.json
+++ b/sdk/deno.json
@@ -1,5 +1,6 @@
{
"name": "@auth-yes/sdk",
"version": "0.1.0",
+ "license": "MIT OR Apache-2.0",
"exports": "./mod.ts"
}
diff --git a/server/deno.json b/server/deno.json
index 88476a4..12fd28d 100644
--- a/server/deno.json
+++ b/server/deno.json
@@ -1,5 +1,6 @@
{
"name": "@auth-yes/server",
"version": "0.1.0",
+ "license": "MIT OR Apache-2.0",
"exports": "./main.ts"
}
diff --git a/spire_ffi/Cargo.toml b/spire_ffi/Cargo.toml
index 410eb29..61b3aab 100644
--- a/spire_ffi/Cargo.toml
+++ b/spire_ffi/Cargo.toml
@@ -2,6 +2,7 @@
name = "spire_ffi"
version = "0.1.0"
edition = "2021"
+license = "MIT OR Apache-2.0"
[lib]
crate-type = ["cdylib"]
diff --git a/tasks/complete/.gitkeep b/tasks/complete/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tasks/complete/2026-0821.01.jul.story.setup-ts.headless-architecture-analysis-0105.md b/tasks/complete/2026-0821.01.jul.story.setup-ts.headless-architecture-analysis-0105.md
new file mode 100644
index 0000000..fbabc45
--- /dev/null
+++ b/tasks/complete/2026-0821.01.jul.story.setup-ts.headless-architecture-analysis-0105.md
@@ -0,0 +1,118 @@
+# TASK METADATA
+
+- **Target Files:** `infra/setup.ts`
+- **Core Objective:** Design a robust, non-interactive (headless) execution mode
+ for `setup.ts` with explicit guardrails to prevent VM hangs.
+- **Dependencies:** `jsr:@cliffy/command` or similar argument parsing library
+ integration may be required for the CLI subcommands.
+- **Additional Important Notes:** Must preserve the existing interactive menu
+ when run without arguments in a TTY environment. Must fail-fast if headless
+ environment is detected without explicit headless flags.
+
+---
+
+## 1. Input Audit
+
+The current interactive wizard in `setup.ts` requests the following inputs and
+configurations across its menus and sub-menus:
+
+### A. Main Menu Actions (`Select.prompt`)
+
+The user is prompted to choose one of the following execution paths:
+
+- `[Test Hub Connection]` -> `test`
+- `[Configure Central Hub]` -> `hub`
+- `[Configure Auth Yes API]` -> `auth`
+- `[Compile Protobuf Definitions]` -> `compile_proto`
+- `[Review Generated Configs]` -> `review`
+- `[Build and Push Hub Image]` -> `build`
+- `[Build and Push Auth Yes Image]` -> `build_auth`
+- `[Generate Edge Handshake]` -> `handshake`
+- `[Exit]` -> `exit`
+
+### B. Hub Setup (`handleHubSetup`)
+
+Requires the following inputs (`SetupConfig`):
+
+- **Container Registry URL** (`Input.prompt`): e.g., `quay.atyg.org`
+- **System Domain Name** (`Input.prompt`): e.g., `system.local`
+- **Database Path on Host** (`Input.prompt`): e.g.,
+ `/volume1/docker/ed-droid/db`
+- **PostgreSQL Password** (`Secret.prompt`): Hidden input, falls back to
+ existing if left blank.
+- **UI Modules** (`Checkbox.prompt`): Multi-select options (`route`, `roi`,
+ `exo`, `log`).
+
+### C. Auth Setup (`handleAuthSetup`)
+
+Requires the following inputs (`AuthSetupConfig`):
+
+- **Container Registry URL** (`Input.prompt`): e.g., `quay.atyg.org`
+- **Auth Domain Name** (`Input.prompt`): e.g., `auth.system.local`
+- **Database Path on Host** (`Input.prompt`): e.g.,
+ `/volume1/docker/auth-yes/db`
+- **App Secret for IDP** (`Secret.prompt`): Minimum length 16.
+- **PostgreSQL Password** (`Secret.prompt`): Hidden input, falls back to
+ existing if left blank.
+
+## 2. Headless Architecture Proposal
+
+To support non-interactive environments (like CI/CD or automated VM
+provisioning) without sacrificing the existing developer experience, a **hybrid
+CLI Subcommand + Environment Variable approach** is recommended.
+
+### A. Subcommand Routing
+
+The interactive "Main Menu" should be mapped to explicit CLI subcommands. For
+example:
+
+- `deno run -A setup.ts hub` (corresponds to `[Configure Central Hub]`)
+- `deno run -A setup.ts auth` (corresponds to `[Configure Auth Yes API]`)
+- `deno run -A setup.ts build` (corresponds to `[Build and Push Hub Image]`)
+
+### B. Configuration Injection (Hybrid Approach)
+
+For subcommands that require configuration (like `hub` and `auth`), we should
+use a combination of CLI flags for non-sensitive data and environment variables
+for secrets.
+
+**Example for Hub Setup:**
+`deno run -A setup.ts hub --auto --registry="quay.atyg.org" --domain="system.local" --db-path="/var/lib/db" --modules="route,log"`
+_Secrets:_ The PostgreSQL password should be read from the environment (e.g.,
+`POSTGRES_PASSWORD`), failing explicitly if it is not provided.
+
+**Example for Auth Setup:**
+`deno run -A setup.ts auth --auto --registry="quay.atyg.org" --domain="auth.system.local" --db-path="/var/lib/auth-db"`
+_Secrets:_ The PostgreSQL password and App Secret should be read from the
+environment (e.g., `POSTGRES_PASSWORD`, `APP_SECRET`), failing explicitly if not
+provided.
+
+### C. Fallback to Interactive
+
+If `setup.ts` is executed without any subcommands or arguments (i.e.,
+`deno run -A setup.ts`), the script should verify it is in a terminal (see
+Guardrails) and immediately launch the existing interactive `runSetupWizard()`.
+
+## 3. Execution Guardrails
+
+To absolutely prevent the script from hanging headless VMs by accidentally
+blocking on a `prompt()`, we must implement strict, early-exit guardrails.
+
+1. **Terminal Detection (`fail-fast`):** At the very beginning of execution,
+ check `Deno.stdin.isTerminal()`. If it is `false` (meaning we are running
+ headless/non-interactive), the script **must** inspect the provided
+ arguments. If explicit headless subcommands or a flag like
+ `--auto`/`--headless` are **not** present, the script must abort immediately
+ with a non-zero exit code and a clear error message (e.g.,
+ `"Error: Non-interactive environment detected, but no explicit CLI subcommands or --auto flag were provided. Aborting to prevent hangs."`).
+
+2. **Clean Exit on Help/Version:** By utilizing a robust CLI parsing library
+ (like Cliffy's `Command`), flags such as `--help` or `--version` will be
+ intercepted _before_ any application logic or wizard is initialized, ensuring
+ a clean `exit(0)`.
+
+3. **Strict Validation in Headless Mode:** When running a subcommand in headless
+ mode (e.g., `setup.ts hub --auto`), the script must validate that _all_
+ required inputs (either via flags or environment variables) are present
+ before proceeding. If any are missing, it must `throw` or `Deno.exit(1)`
+ rather than falling back to an interactive prompt.
diff --git a/tasks/complete/2026-0821.01.jul.story.staging.extract-auth-yes-1854.md b/tasks/complete/2026-0821.01.jul.story.staging.extract-auth-yes-1854.md
new file mode 100644
index 0000000..61d3230
--- /dev/null
+++ b/tasks/complete/2026-0821.01.jul.story.staging.extract-auth-yes-1854.md
@@ -0,0 +1,97 @@
+# TASK METADATA
+
+- **Target Files:** `scripts/stage-auth-yes.ts` (new script)
+- **Core Objective:** Design a staging extraction script that selectively copies
+ and structures the `auth-yes` workspace into `.extract_auth_yes/`, creating a
+ pristine, independently verifiable directory ready for a new repository.
+- **Dependencies:** Deno for executing the script and tasks; Rust toolchain for
+ `cargo check`.
+- **Additional Important Notes:**
+ - The script must ensure `.extract_auth_yes/` is completely cleaned/removed
+ prior to copying.
+ - The new workspace must strictly exclude `ed-droid` game logic (`core/`,
+ `modules/`, `edge/`, `main.ts`, parent `tasks/`).
+ - An automated verification step (e.g. `--verify` flag) should run inside the
+ staged directory.
+ - Static asset serving in `ui/mod.ts` must update from `./auth-yes/ui` to
+ `./ui`.
+
+---
+
+## Architectural Considerations & Risks
+
+- **Risks:**
+ - **Incomplete Workspaces:** Generating a standalone `deno.json` dynamically
+ requires ensuring all necessary `workspace` paths and `compilerOptions`
+ (such as `jsx` and `jsxImportSource` for Hono SSR) from the monorepo root
+ are correctly transferred or constructed. Missing imports could lead to
+ failed dependency resolutions in the staged copy.
+ - **Pathing Issues:** If file paths hardcoded in the code assume the current
+ monorepo structure (such as
+ `uiApp.get("/public/*", serveStatic({ root: "./auth-yes/ui" }))` in
+ `ui/mod.ts`), these must be cleanly adjusted to `./ui` so static asset
+ delivery succeeds.
+ - **Build Context:** `Dockerfile` context and Rust FFI build paths must align
+ with the new flat directory layout inside `.extract_auth_yes/`.
+- **Alternatives:** We could use a standard bash script for simplicity, but
+ given this project heavily utilizes Deno, building this as a
+ `scripts/stage-auth-yes.ts` script allows leveraging Deno's strong filesystem
+ APIs, child processes for tasks (Deno `Command` API), and provides easier
+ multi-platform support. Using Deno over bash is cleaner and more native to
+ this environment.
+
+## Proposed Implementation
+
+### 1. Script Initialization and Cleanup
+
+- Create `scripts/stage-auth-yes.ts`.
+- Implement a CLI using `@cliffy/command` (or standard `Deno.args` parsing) to
+ optionally accept a `--verify` flag.
+- Execute `Deno.remove` with `{ recursive: true }` on `.extract_auth_yes/` to
+ ensure a deterministic, clean slate.
+- Recreate `.extract_auth_yes/` using `Deno.mkdir`.
+
+### 2. Selective Copy Process
+
+Use `Deno.copy` from `std/fs` or recursively traverse and copy the following
+specific mappings into `.extract_auth_yes/`:
+
+- `auth-yes/sdk/` -> `./sdk/`
+- `auth-yes/server/` -> `./server/`
+- `auth-yes/ui/` -> `./ui/`
+- `proto/` -> `./proto/`
+- `spire_ffi/` -> `./spire_ffi/`
+- `auth-yes/Dockerfile` -> `./Dockerfile`
+- `infra/compose.auth.yml` & `infra/compose.spire.yml` -> `./infra/`
+- `infra/.env.auth` -> `./infra/.env.example`
+- `auth-yes/Custom IAM Architecture Analysis v2.md` -> `./README.md`
+
+### 3. Path Adjustments & Standalone Root Configuration
+
+- In the staged `ui/mod.ts`, replace `root: "./auth-yes/ui"` with
+ `root: "./ui"`.
+- Programmatically construct a new `deno.json` object.
+- Include `"workspace": ["./sdk", "./server", "./ui"]`.
+- Retain `tasks`, `lint`, and `compilerOptions` definitions necessary to execute
+ quality gates (especially `jsx` for `ui/`).
+- Include the `imports` necessary for `auth-yes` (from the monorepo's root
+ `deno.json`).
+- Write this configuration to `.extract_auth_yes/deno.json`.
+- Create a standard `.gitignore` file ignoring `spire_ffi/target/`, `.env`, and
+ OS temp files.
+
+### 4. Automated Verification Testing
+
+If the `--verify` flag is provided (or if run automatically by default), spawn
+Deno child processes within the `cwd: ".extract_auth_yes/"` to execute:
+
+- `deno fmt --check`
+- `deno task lint` (or `deno lint`)
+- `deno check main.ts server/**/*.ts sdk/**/*.ts ui/**/*.ts` (or appropriate
+ paths in the staged structure)
+- `deno test -A`
+- `cargo check --manifest-path spire_ffi/Cargo.toml`
+
+If any process exits with a non-zero code, log a failure message and exit the
+script with an error code, effectively serving as an independent quality gate
+before treating the staging directory as "ready for git init".
diff --git a/tasks/complete/2026-0821.02.jul.arch.setup-ts.shared-cli-architecture-1857.md b/tasks/complete/2026-0821.02.jul.arch.setup-ts.shared-cli-architecture-1857.md
new file mode 100644
index 0000000..2b1ba24
--- /dev/null
+++ b/tasks/complete/2026-0821.02.jul.arch.setup-ts.shared-cli-architecture-1857.md
@@ -0,0 +1,95 @@
+# TASK METADATA
+
+- **Target Files:** `infra/setup.ts`, `auth-yes/infra/setup.ts`
+- **Core Objective:** Design a standardized 4-Layer CLI architecture to split
+ the monolithic `setup.ts` into discrete, context-specific scripts for
+ `ed-droid` and `auth-yes` while ensuring identical dual-mode ergonomics and
+ adopting the concise `infra/` directory standard.
+- **Dependencies:** None.
+- **Additional Important Notes:**
+ - Standardize directory name to `infra/` (replacing `infra/`).
+ - Podman compose commands must explicitly specify `--project-name` (e.g.,
+ `--project-name auth-yes`, `--project-name ed-droid`).
+ - Recommend a template approach over a shared library initially to avoid
+ external bootstrap dependencies during local dev.
+ - Maintain existing UX conventions via `@cliffy` and `@std/fmt/colors`.
+
+---
+
+## Architectural Considerations & Risks
+
+- **Risks:**
+ - **Divergence:** Splitting into two scripts introduces the risk of the
+ architectures drifting apart over time if the 4-layer template is not
+ strictly adhered to.
+ - **Duplication:** While mitigating external dependencies, the template
+ approach inherently requires code duplication of standard patterns (e.g.,
+ config loading, command trees, TUI loops).
+ - **Bootstrap Failure:** If an external library (e.g., from JSR) is used
+ immediately, offline environments or initial setups might fail to run the
+ script.
+- **Alternatives:**
+ - **Shared Micro-Library:** Extracting the common CLI framework into a
+ standalone package like `@atyg/setup-cli` on JSR. This provides maximum
+ DRYness but introduces external dependency risks during local bootstrapping.
+ **Recommended as a future phase** once more standalone services exist.
+ - **Unified Monolith (Current State):** Keep the unified `infra/setup.ts`.
+ While simple for a single repo, it violates separation of concerns since
+ `auth-yes` is treated as a standalone workspace/repository.
+
+## Proposed Implementation
+
+### 1. Define the 4-Layer Architectural Template
+
+Both the `ed-droid` and `auth-yes` CLI scripts (`infra/setup.ts`) must strictly
+implement this pattern:
+
+1. **Config/Dotenv Layer:** Functions handling purely I/O reads/writes (e.g.,
+ `readEnv()`, `generateEnv()`).
+2. **Cliffy Command Tree (Headless/Scriptable):** Definition of the CLI
+ structure with standard subcommand verbs:
+ - `config`: Generates/reviews `.env` and compose files non-interactively.
+ - `build`: Executes `podman build` and pushes to registry.
+ - `test`: Verifies health checks and service connectivity.
+ - `deploy`: Runs
+ `podman-compose --project-name --env-file -f up -d`.
+ - Context-specific subcommands (`spire`, `compile_proto` for `auth-yes`;
+ `modules`, `handshake` for `ed-droid`).
+3. **Interactive TUI Loop:** The fallback wizard for human operators, using
+ `@cliffy/prompt` to guide users if no subcommands/flags are passed.
+4. **Execution Engine:** The core logic driving side effects like generating
+ files, running container commands with explicit `--project-name`, or network
+ requests.
+
+### 2. Standardize on `infra/` Directory & Split `setup.ts`
+
+- **Directory Naming:** Adopt the concise `infra/` convention across all
+ repositories (e.g., `infra/setup.ts`, `infra/compose.yml`,
+ `infra/.env.example`).
+- **`auth-yes/infra/setup.ts`:**
+ - Exclusively manages Auth-Yes, Spire/SPIFFE mTLS, Valkey/Postgres stack, and
+ protobuf compilation.
+ - Uses `--project-name auth-yes` for all compose lifecycle commands.
+- **`ed-droid/infra/setup.ts`:**
+ - Exclusively manages the Central Hub, UI modules, edge client handshake, and
+ hub images.
+ - Uses `--project-name ed-droid` for all compose lifecycle commands.
+
+### 3. Standardize Ergonomics, UX & Deno Tasks
+
+Ensure both target files share identical ergonomics:
+
+- Utilize `@std/fmt/colors` consistently for logging and prompts.
+- Maintain dual-mode behavior: Fail fast with clear errors in non-interactive
+ environments unless explicit subcommands are passed.
+- Add standard Deno task in both `deno.json` files:
+ ```json
+ "tasks": {
+ "setup": "deno run -A infra/setup.ts"
+ }
+ ```
+
+### 4. Future Phase Consideration
+
+Document within the repository the migration path to an `@atyg/setup-cli` JSR
+package once the ecosystem scales to additional standalone repositories.
diff --git a/tasks/complete/2026-0821.03.jul.story.auth-yes.modular-workspace-1855.md b/tasks/complete/2026-0821.03.jul.story.auth-yes.modular-workspace-1855.md
new file mode 100644
index 0000000..1ffdb50
--- /dev/null
+++ b/tasks/complete/2026-0821.03.jul.story.auth-yes.modular-workspace-1855.md
@@ -0,0 +1,80 @@
+# TASK METADATA
+
+- **Target Files:** `auth-yes/deno.json`, `auth-yes/sdk/deno.json`,
+ `auth-yes/server/deno.json`, `auth-yes/ui/deno.json`, `auth-yes/sdk/gen/*`
+- **Core Objective:** Architect the modular Deno workspace structure for the
+ standalone auth-yes repository to ensure `@auth-yes/sdk` is fully isolated and
+ cleanly exportable.
+- **Dependencies:** None.
+- **Additional Important Notes:**
+ - Package naming standard: `@auth-yes/sdk`, `@auth-yes/server`,
+ `@auth-yes/ui`.
+ - `@auth-yes/sdk` must have zero database or server imports and be consumable
+ independently.
+ - UI JSX compilation relies on `"jsx": "react-jsx"` with
+ `"jsxImportSource": "jsr:@hono/hono@4/jsx"` (pure Hono SSR, zero React
+ dependencies).
+
+---
+
+## Architectural Considerations & Risks
+
+- **Risks:** The primary risk is a circular dependency or importing server-side
+ logic into the SDK, which would break the isolation of the SDK. If the SDK
+ depends on the server, external consumers (like ed-droid) will be forced to
+ download unnecessary and potentially insecure backend dependencies.
+- **Dependency Decoupling for Contracts:** The generated ConnectRPC contracts
+ (`auth_pb.ts` and `auth_connect.ts`) currently reside in `server/gen/`. To
+ ensure the SDK has 100% zero dependencies on `./server`, these generated files
+ must be moved into the SDK (e.g., `sdk/gen/`). This way, consumers of
+ `@auth-yes/sdk` will have all necessary type definitions and client stubs
+ without needing any server files. The server package can then import these
+ service contracts from the SDK.
+- **JSX Compiler Standard (Zero React):** TypeScript and Deno use
+ `"jsx": "react-jsx"` as the compiler standard for the modern JSX transform.
+ When paired with `"jsxImportSource": "jsr:@hono/hono@4/jsx"`, TypeScript
+ targets Hono's lightweight native SSR engine without pulling in any React
+ runtime or dependencies.
+- **Alternatives:** We could extract the proto contracts into a separate fourth
+ workspace member (e.g., `api-contracts`). However, moving them directly into
+ the SDK is simpler and provides exactly what external consumers need in a
+ single package.
+
+## Proposed Implementation
+
+### Phase 1: Root Workspace Definition
+
+1. Create a root `deno.json` in `auth-yes/` managing workspace members:
+ `"./sdk"`, `"./server"`, `"./ui"`.
+2. Configure workspace-wide tasks (`lint`, `fmt`, `check`, `test`).
+
+### Phase 2: SDK Package Isolation
+
+1. Create `auth-yes/sdk/deno.json` with package name `@auth-yes/sdk`, version
+ `0.1.0`, and export definition (`"exports": "./mod.ts"`).
+2. Move the generated ConnectRPC contracts from `server/gen/` into `sdk/gen/`.
+3. Update `sdk/mod.ts` to export client functions and proto types, ensuring zero
+ imports point to `../server` or `../ui`.
+
+### Phase 3: Server and UI Package Configuration
+
+1. Create `auth-yes/server/deno.json` with package name `@auth-yes/server`.
+2. Update `auth-yes/server/main.ts` to import service contracts directly from
+ `@auth-yes/sdk`.
+3. Create `auth-yes/ui/deno.json` with package name `@auth-yes/ui`, including:
+ ```json
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "jsxImportSource": "jsr:@hono/hono@4/jsx"
+ }
+ ```
+4. Verify that the Rust `spire_ffi` crate is properly referenced by `server/`
+ and is not exposed or imported by `@auth-yes/sdk`.
+
+### Phase 4: Workspace Verification & Quality Gates
+
+1. Run `deno fmt` across all workspace members.
+2. Run `deno lint` to ensure zero import violations.
+3. Run `deno check sdk/**/*.ts server/**/*.ts ui/**/*.ts` to verify clean
+ cross-package type resolutions.
+4. Run `deno test -A` to verify test suite execution.
diff --git a/tasks/new/.gitkeep b/tasks/new/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tasks/new/2026-0821.01.jul.story.auth-yes.extract-standalone-repo-1828.md b/tasks/new/2026-0821.01.jul.story.auth-yes.extract-standalone-repo-1828.md
new file mode 100644
index 0000000..739a323
--- /dev/null
+++ b/tasks/new/2026-0821.01.jul.story.auth-yes.extract-standalone-repo-1828.md
@@ -0,0 +1,84 @@
+# TASK METADATA
+
+- **Target Files:**
+ - `auth-yes/*`
+ - `spire_ffi/*`
+ - `infra/setup.ts`
+ - `deno.json`
+- **Core Objective:** Extract `auth-yes`, `spire_ffi`, and its related infra
+ scripts and configurations into a pristine, standalone directory representing
+ a new isolated workspace repository.
+- **Dependencies:** None.
+- **Additional Important Notes:** The extracted code must represent a modular
+ Deno workspace containing `sdk/`, `server/`, `ui/`, and `spire_ffi/`. All
+ auth-related infra setup must be excised from the parent repository
+ (`ed-droid`), and the `auth-yes` databases (Postgres, Valkey) must be 100%
+ isolated. The SDK should be ready for potential JSR/Git distribution.
+
+---
+
+## Architectural Considerations & Risks
+
+- **Risks:**
+ - **Shared Dependencies:** Breaking internal imports inside the `ed-droid`
+ mono-repo that rely on `auth-yes` internals. The `ed-droid` core must pivot
+ to relying purely on HTTP/ForwardAuth and the `@auth-yes/sdk`.
+ - **FFI Rust Compilation:** Moving `spire_ffi` could break relative path cargo
+ configurations, `.gitignore` behaviors, or Docker multi-stage build contexts
+ in the new repository.
+ - **Infrastructure Script Bloat:** Moving setup logic from `infra/setup.ts`
+ into the standalone repo requires untangling Deno CLI commands, file
+ generation logic (e.g., `compose.auth.yml`), and configuration parsing
+ currently tightly bound to `ed-droid`'s main setup process.
+
+- **Alternatives:**
+ - **Alternative Extraction Tooling:** Instead of manually copying and
+ rewriting imports, we could use Git history rewriting tools (like
+ `git filter-repo`) to extract `auth-yes` while preserving git history.
+ However, given the requirement to synthesize a clean staging directory ready
+ for `git init`, a structured scripted extraction and clean workspace
+ definition is the preferred, native, and cleaner approach here.
+
+## Proposed Implementation
+
+### Phase 1: Establish the Staging Skeleton
+
+1. Create an extraction staging directory (e.g., `.extract_auth_yes/`).
+2. Initialize a modular `deno.json` at the root of the staging directory
+ defining workspaces: `sdk`, `server`, and `ui`.
+3. Scaffold the target directories: `sdk/`, `server/`, `ui/`, `spire_ffi/`, and
+ `infra/`.
+
+### Phase 2: Code & Configuration Extraction
+
+1. **SDK, Server, & UI:** Migrate the contents of `auth-yes/sdk`,
+ `auth-yes/server`, and `auth-yes/ui` into their respective workspace
+ directories in the staging area. Update internal relative imports.
+2. **SDK Export:** Ensure `sdk/deno.json` exports `mod.ts` cleanly so it can be
+ consumed independently (no JSR publishing required immediately).
+3. **Rust FFI:** Move `spire_ffi/` completely into the staging area. Verify
+ `Cargo.toml` and `build.rs` paths remain valid.
+
+### Phase 3: Infrastructure Extraction
+
+1. Extract `auth-yes` and Spire specific setup logic from
+ `ed-droid/infra/setup.ts` and author a dedicated setup tool in the standalone
+ repository (e.g., `infra/setup.ts`).
+2. The standalone repo's setup tool must independently handle
+ `compose.auth.yml`, `compose.spire.yml`, and environment templates.
+3. Completely remove auth and spire logic from the parent
+ `ed-droid/infra/setup.ts`.
+
+### Phase 4: CI/CD & Docker Boundaries
+
+1. Copy and adjust the multi-stage `Dockerfile` into the standalone root,
+ ensuring the build context supports Deno workspaces (e.g., copying the root
+ `deno.json` and selectively copying workspace members).
+2. Validate that `auth-yes` explicitly mandates its own PostgreSQL and Valkey
+ data stores, ensuring absolute zero direct database coupling with `ed-droid`.
+
+### Phase 5: Final Review & Preparation
+
+1. Run `deno fmt`, `deno lint`, and `deno check` against the staged workspace.
+2. Ensure the `.extract_auth_yes/` directory is pristine, isolated, and ready to
+ be initialized as a fresh remote Git repository (`git init`).
diff --git a/tasks/wip/.gitkeep b/tasks/wip/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/ui/deno.json b/ui/deno.json
index 22f0bb8..78b1f62 100644
--- a/ui/deno.json
+++ b/ui/deno.json
@@ -1,6 +1,7 @@
{
"name": "@auth-yes/ui",
"version": "0.1.0",
+ "license": "MIT OR Apache-2.0",
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "jsr:@hono/hono@4/jsx"