chore: adopt dual licensing and import task history & scaffolding

- Add LICENSE-MIT and LICENSE-APACHE for dual MIT / Apache-2.0 distribution
- Update root LICENSE pointer, README.md, Deno workspace manifests, and Cargo.toml
- Add deno.lock dependency lockfile
- Format AGENTS.md system guidelines
- Import task lifecycle scaffolding and historical story specifications (extract-auth-yes, setup-ts architecture, modular workspace)
This commit is contained in:
Tyler Gillispie 2026-08-21 15:20:36 -07:00
parent 9b2367e2aa
commit 474cc177ce
19 changed files with 1132 additions and 27 deletions

View File

@ -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`)

23
LICENSE
View File

@ -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

201
LICENSE-APACHE Normal file
View File

@ -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.

21
LICENSE-MIT Normal file
View File

@ -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.

View File

@ -453,3 +453,14 @@ latency.
| **Phase 2** | **Zero-Trust App Mesh (Backend)** | - ConnectRPC / gRPC transport<br>- SPIFFE/SPIRE mTLS client certificate validation<br>- Default-deny RBAC grant verification<br>- ForwardAuth `/api/forward-auth` endpoint | **COMPLETED** |
| **Phase 3** | **Admin Console UI Views (Current)** | - `/admin/apps` Application Registry UI<br>- `/admin/invites` Multi-Type Token Provisioning UI<br>- `/admin/users/:id` App RBAC Grant Manager UI<br>- Domain wildcard cookie (`.atyg.org`) deployment | **READY FOR BUILD** |
| **Phase 4** | **Edge Hardening & Future Scoping** | - Traefik Tier 1 global ForwardAuth fallback configuration<br>- Traefik Tier 2 ForwardAuth container routing<br>- 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`

View File

@ -4,6 +4,7 @@
"./server",
"./ui"
],
"license": "MIT OR Apache-2.0",
"tasks": {
"lint": "deno lint",
"fmt": "deno fmt",

391
deno.lock generated Normal file
View File

@ -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"
]
}
}
}
}

View File

@ -1,5 +1,6 @@
{
"name": "@auth-yes/sdk",
"version": "0.1.0",
"license": "MIT OR Apache-2.0",
"exports": "./mod.ts"
}

View File

@ -1,5 +1,6 @@
{
"name": "@auth-yes/server",
"version": "0.1.0",
"license": "MIT OR Apache-2.0",
"exports": "./main.ts"
}

View File

@ -2,6 +2,7 @@
name = "spire_ffi"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
[lib]
crate-type = ["cdylib"]

0
tasks/complete/.gitkeep Normal file
View File

View File

@ -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.

View File

@ -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".

View File

@ -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 <name> --env-file <env> -f <compose> 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.

View File

@ -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.

0
tasks/new/.gitkeep Normal file
View File

View File

@ -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`).

0
tasks/wip/.gitkeep Normal file
View File

View File

@ -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"