constella 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +53 -0
- package/.next/build-manifest.json +20 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +36 -0
- package/.next/react-loadable-manifest.json +14 -0
- package/.next/required-server-files.js +343 -0
- package/.next/required-server-files.json +343 -0
- package/.next/routes-manifest.json +362 -0
- package/.next/server/app/(app)/activity/page.js +2 -0
- package/.next/server/app/(app)/activity/page.js.nft.json +1 -0
- package/.next/server/app/(app)/activity/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/agents/[handle]/page.js +18 -0
- package/.next/server/app/(app)/agents/[handle]/page.js.nft.json +1 -0
- package/.next/server/app/(app)/agents/[handle]/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/code/page.js +2 -0
- package/.next/server/app/(app)/code/page.js.nft.json +1 -0
- package/.next/server/app/(app)/code/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/config/page.js +2 -0
- package/.next/server/app/(app)/config/page.js.nft.json +1 -0
- package/.next/server/app/(app)/config/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/costs/page.js +2 -0
- package/.next/server/app/(app)/costs/page.js.nft.json +1 -0
- package/.next/server/app/(app)/costs/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/cron/page.js +2 -0
- package/.next/server/app/(app)/cron/page.js.nft.json +1 -0
- package/.next/server/app/(app)/cron/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/dashboard/page.js +2 -0
- package/.next/server/app/(app)/dashboard/page.js.nft.json +1 -0
- package/.next/server/app/(app)/dashboard/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/docs/[id]/page.js +2 -0
- package/.next/server/app/(app)/docs/[id]/page.js.nft.json +1 -0
- package/.next/server/app/(app)/docs/[id]/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/docs/page.js +2 -0
- package/.next/server/app/(app)/docs/page.js.nft.json +1 -0
- package/.next/server/app/(app)/docs/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/github/page.js +2 -0
- package/.next/server/app/(app)/github/page.js.nft.json +1 -0
- package/.next/server/app/(app)/github/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/goals/page.js +2 -0
- package/.next/server/app/(app)/goals/page.js.nft.json +1 -0
- package/.next/server/app/(app)/goals/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/inbox/page.js +2 -0
- package/.next/server/app/(app)/inbox/page.js.nft.json +1 -0
- package/.next/server/app/(app)/inbox/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/knowledge/page.js +3 -0
- package/.next/server/app/(app)/knowledge/page.js.nft.json +1 -0
- package/.next/server/app/(app)/knowledge/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/models/page.js +2 -0
- package/.next/server/app/(app)/models/page.js.nft.json +1 -0
- package/.next/server/app/(app)/models/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/notifications/page.js +2 -0
- package/.next/server/app/(app)/notifications/page.js.nft.json +1 -0
- package/.next/server/app/(app)/notifications/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/org/page.js +2 -0
- package/.next/server/app/(app)/org/page.js.nft.json +1 -0
- package/.next/server/app/(app)/org/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/organizations/page.js +2 -0
- package/.next/server/app/(app)/organizations/page.js.nft.json +1 -0
- package/.next/server/app/(app)/organizations/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/page.js +3 -0
- package/.next/server/app/(app)/page.js.nft.json +1 -0
- package/.next/server/app/(app)/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/planner/page.js +2 -0
- package/.next/server/app/(app)/planner/page.js.nft.json +1 -0
- package/.next/server/app/(app)/planner/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/plugins/page.js +2 -0
- package/.next/server/app/(app)/plugins/page.js.nft.json +1 -0
- package/.next/server/app/(app)/plugins/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/pm/page.js +2 -0
- package/.next/server/app/(app)/pm/page.js.nft.json +1 -0
- package/.next/server/app/(app)/pm/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/prepare-deploy/page.js +19 -0
- package/.next/server/app/(app)/prepare-deploy/page.js.nft.json +1 -0
- package/.next/server/app/(app)/prepare-deploy/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/profile/page.js +2 -0
- package/.next/server/app/(app)/profile/page.js.nft.json +1 -0
- package/.next/server/app/(app)/profile/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/pulse/page.js +2 -0
- package/.next/server/app/(app)/pulse/page.js.nft.json +1 -0
- package/.next/server/app/(app)/pulse/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/reports/[id]/page.js +3 -0
- package/.next/server/app/(app)/reports/[id]/page.js.nft.json +1 -0
- package/.next/server/app/(app)/reports/[id]/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/reports/page.js +5 -0
- package/.next/server/app/(app)/reports/page.js.nft.json +1 -0
- package/.next/server/app/(app)/reports/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/routines/page.js +2 -0
- package/.next/server/app/(app)/routines/page.js.nft.json +1 -0
- package/.next/server/app/(app)/routines/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/search/page.js +2 -0
- package/.next/server/app/(app)/search/page.js.nft.json +1 -0
- package/.next/server/app/(app)/search/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/security/page.js +2 -0
- package/.next/server/app/(app)/security/page.js.nft.json +1 -0
- package/.next/server/app/(app)/security/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/skills/page.js +18 -0
- package/.next/server/app/(app)/skills/page.js.nft.json +1 -0
- package/.next/server/app/(app)/skills/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/tasks/page.js +2 -0
- package/.next/server/app/(app)/tasks/page.js.nft.json +1 -0
- package/.next/server/app/(app)/tasks/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/test-dev/page.js +2 -0
- package/.next/server/app/(app)/test-dev/page.js.nft.json +1 -0
- package/.next/server/app/(app)/test-dev/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(app)/update/page.js +2 -0
- package/.next/server/app/(app)/update/page.js.nft.json +1 -0
- package/.next/server/app/(app)/update/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(auth)/login/page.js +2 -0
- package/.next/server/app/(auth)/login/page.js.nft.json +1 -0
- package/.next/server/app/(auth)/login/page_client-reference-manifest.js +1 -0
- package/.next/server/app/(auth)/onboarding/page.js +18 -0
- package/.next/server/app/(auth)/onboarding/page.js.nft.json +1 -0
- package/.next/server/app/(auth)/onboarding/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_global-error/page.js +32 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +16 -0
- package/.next/server/app/_global-error.rsc +15 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +15 -0
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_global-error.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_head.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_index.segment.rsc +6 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page.js +2 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/api/auth/[...all]/route.js +1 -0
- package/.next/server/app/api/auth/[...all]/route.js.nft.json +1 -0
- package/.next/server/app/api/auth/[...all]/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/cron/tick/route.js +52 -0
- package/.next/server/app/api/cron/tick/route.js.nft.json +1 -0
- package/.next/server/app/api/cron/tick/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/dev-login/route.js +1 -0
- package/.next/server/app/api/dev-login/route.js.nft.json +1 -0
- package/.next/server/app/api/dev-login/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/locks/acquire/route.js +1 -0
- package/.next/server/app/api/locks/acquire/route.js.nft.json +1 -0
- package/.next/server/app/api/locks/acquire/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/models/progress/route.js +1 -0
- package/.next/server/app/api/models/progress/route.js.nft.json +1 -0
- package/.next/server/app/api/models/progress/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/passkey/authenticate/options/route.js +1 -0
- package/.next/server/app/api/passkey/authenticate/options/route.js.nft.json +1 -0
- package/.next/server/app/api/passkey/authenticate/options/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/passkey/authenticate/verify/route.js +1 -0
- package/.next/server/app/api/passkey/authenticate/verify/route.js.nft.json +1 -0
- package/.next/server/app/api/passkey/authenticate/verify/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/passkey/register/options/route.js +1 -0
- package/.next/server/app/api/passkey/register/options/route.js.nft.json +1 -0
- package/.next/server/app/api/passkey/register/options/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/passkey/register/verify/route.js +1 -0
- package/.next/server/app/api/passkey/register/verify/route.js.nft.json +1 -0
- package/.next/server/app/api/passkey/register/verify/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/stream/route.js +4 -0
- package/.next/server/app/api/stream/route.js.nft.json +1 -0
- package/.next/server/app/api/stream/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/sync/file/route.js +2 -0
- package/.next/server/app/api/sync/file/route.js.nft.json +1 -0
- package/.next/server/app/api/sync/file/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/telegram/poll/route.js +15 -0
- package/.next/server/app/api/telegram/poll/route.js.nft.json +1 -0
- package/.next/server/app/api/telegram/poll/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/upload/route.js +1 -0
- package/.next/server/app/api/upload/route.js.nft.json +1 -0
- package/.next/server/app/api/upload/route_client-reference-manifest.js +1 -0
- package/.next/server/app/api/v1/[[...path]]/route.js +1 -0
- package/.next/server/app/api/v1/[[...path]]/route.js.nft.json +1 -0
- package/.next/server/app/api/v1/[[...path]]/route_client-reference-manifest.js +1 -0
- package/.next/server/app-paths-manifest.json +53 -0
- package/.next/server/chunks/1003.js +1 -0
- package/.next/server/chunks/127.js +26 -0
- package/.next/server/chunks/1388.js +1 -0
- package/.next/server/chunks/1408.js +21 -0
- package/.next/server/chunks/1572.js +1 -0
- package/.next/server/chunks/1591.js +24 -0
- package/.next/server/chunks/1619.js +188 -0
- package/.next/server/chunks/162.js +1 -0
- package/.next/server/chunks/1881.js +1 -0
- package/.next/server/chunks/1968.js +1 -0
- package/.next/server/chunks/2297.js +348 -0
- package/.next/server/chunks/2341.js +1 -0
- package/.next/server/chunks/2517.js +1 -0
- package/.next/server/chunks/2549.js +1 -0
- package/.next/server/chunks/259.js +14 -0
- package/.next/server/chunks/2599.js +1 -0
- package/.next/server/chunks/260.js +1 -0
- package/.next/server/chunks/2867.js +147 -0
- package/.next/server/chunks/3018.js +1 -0
- package/.next/server/chunks/3050.js +18 -0
- package/.next/server/chunks/3085.js +12 -0
- package/.next/server/chunks/3131.js +1 -0
- package/.next/server/chunks/3242.js +1 -0
- package/.next/server/chunks/3266.js +15 -0
- package/.next/server/chunks/3524.js +1 -0
- package/.next/server/chunks/3527.js +479 -0
- package/.next/server/chunks/3533.js +869 -0
- package/.next/server/chunks/3550.js +1 -0
- package/.next/server/chunks/3609.js +2 -0
- package/.next/server/chunks/3667.js +462 -0
- package/.next/server/chunks/3760.js +4 -0
- package/.next/server/chunks/4679.js +1 -0
- package/.next/server/chunks/4804.js +1 -0
- package/.next/server/chunks/4832.js +2 -0
- package/.next/server/chunks/4853.js +1 -0
- package/.next/server/chunks/4979.js +67 -0
- package/.next/server/chunks/5060.js +1 -0
- package/.next/server/chunks/5278.js +1 -0
- package/.next/server/chunks/5614.js +1 -0
- package/.next/server/chunks/5818.js +1 -0
- package/.next/server/chunks/6479.js +1 -0
- package/.next/server/chunks/6658.js +1 -0
- package/.next/server/chunks/6706.js +1 -0
- package/.next/server/chunks/6719.js +1 -0
- package/.next/server/chunks/678.js +1 -0
- package/.next/server/chunks/683.js +1 -0
- package/.next/server/chunks/6862.js +1 -0
- package/.next/server/chunks/6882.js +1 -0
- package/.next/server/chunks/7037.js +1 -0
- package/.next/server/chunks/7107.js +741 -0
- package/.next/server/chunks/73.js +17 -0
- package/.next/server/chunks/7327.js +1 -0
- package/.next/server/chunks/7514.js +1 -0
- package/.next/server/chunks/7622.js +1 -0
- package/.next/server/chunks/7778.js +1 -0
- package/.next/server/chunks/7912.js +1 -0
- package/.next/server/chunks/7949.js +1 -0
- package/.next/server/chunks/7971.js +1 -0
- package/.next/server/chunks/7989.js +1 -0
- package/.next/server/chunks/842.js +22 -0
- package/.next/server/chunks/8762.js +15 -0
- package/.next/server/chunks/8823.js +77 -0
- package/.next/server/chunks/9146.js +4 -0
- package/.next/server/chunks/9676.js +1 -0
- package/.next/server/chunks/9783.js +22 -0
- package/.next/server/chunks/9969.js +3 -0
- package/.next/server/functions-config-manifest.json +18 -0
- package/.next/server/instrumentation.js +1 -0
- package/.next/server/instrumentation.js.nft.json +1 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/middleware.js +18 -0
- package/.next/server/middleware.js.nft.json +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +3 -0
- package/.next/server/prefetch-hints.json +1 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/chunks/1858-339516f78a4b00da.js +1 -0
- package/.next/static/chunks/2320-fc8b39380e69d465.js +2 -0
- package/.next/static/chunks/23550918-ff694f70f4b0648c.js +1 -0
- package/.next/static/chunks/3219-ebb3c23be38c838d.js +1 -0
- package/.next/static/chunks/4263-adecb5b466380b6e.js +1 -0
- package/.next/static/chunks/5479-0cceab68cd0ca9c7.js +1 -0
- package/.next/static/chunks/5701-665b927b06158b76.js +1 -0
- package/.next/static/chunks/5920.6451a68b63918988.js +1 -0
- package/.next/static/chunks/6575-5c9139720bb0f5bf.js +4 -0
- package/.next/static/chunks/6834-4759af1ce7d95fb6.js +32 -0
- package/.next/static/chunks/7509.721cd47a931c5518.js +1 -0
- package/.next/static/chunks/8264-1ca011989ee2b231.js +1 -0
- package/.next/static/chunks/9219-4a39a98b5502d9d1.js +1 -0
- package/.next/static/chunks/9690-53d5222618cbeddb.js +1 -0
- package/.next/static/chunks/app/(app)/activity/page-3973534281ecea81.js +1 -0
- package/.next/static/chunks/app/(app)/agents/[handle]/page-83662a175c098282.js +1 -0
- package/.next/static/chunks/app/(app)/code/page-33979545192cd137.js +1 -0
- package/.next/static/chunks/app/(app)/config/page-9933aed1ca8a85c1.js +1 -0
- package/.next/static/chunks/app/(app)/costs/page-131c4dc580efcc19.js +1 -0
- package/.next/static/chunks/app/(app)/cron/page-53ea1aff998a87ca.js +1 -0
- package/.next/static/chunks/app/(app)/dashboard/page-deed83aaa9d0d447.js +1 -0
- package/.next/static/chunks/app/(app)/docs/[id]/page-38c993d73c0eab4f.js +1 -0
- package/.next/static/chunks/app/(app)/docs/page-bf463b55d0554e86.js +1 -0
- package/.next/static/chunks/app/(app)/error-988cd28480809861.js +1 -0
- package/.next/static/chunks/app/(app)/github/page-62678b4e82dfecb6.js +1 -0
- package/.next/static/chunks/app/(app)/goals/page-4adb426fe1c96106.js +1 -0
- package/.next/static/chunks/app/(app)/inbox/page-e347dc55ab467310.js +1 -0
- package/.next/static/chunks/app/(app)/knowledge/page-65393a045b4349be.js +1 -0
- package/.next/static/chunks/app/(app)/layout-7f65675705b011d8.js +1 -0
- package/.next/static/chunks/app/(app)/models/page-e01f1dd7e49a2951.js +1 -0
- package/.next/static/chunks/app/(app)/notifications/page-56548ac87aef00da.js +1 -0
- package/.next/static/chunks/app/(app)/org/page-699e6a6dc0db7d81.js +1 -0
- package/.next/static/chunks/app/(app)/organizations/page-36051a380a7e8eb7.js +1 -0
- package/.next/static/chunks/app/(app)/page-7d1011a566f81520.js +1 -0
- package/.next/static/chunks/app/(app)/planner/page-dab7ced94083373a.js +1 -0
- package/.next/static/chunks/app/(app)/plugins/page-5b5a1f53389be42e.js +1 -0
- package/.next/static/chunks/app/(app)/pm/page-0de5c08c0b227bb0.js +1 -0
- package/.next/static/chunks/app/(app)/prepare-deploy/page-e426038552df8d41.js +1 -0
- package/.next/static/chunks/app/(app)/profile/page-608dfcaf8aae0a69.js +1 -0
- package/.next/static/chunks/app/(app)/pulse/page-309ccaca91de1faa.js +1 -0
- package/.next/static/chunks/app/(app)/reports/[id]/page-53ea1aff998a87ca.js +1 -0
- package/.next/static/chunks/app/(app)/reports/page-68cdc6dcfa472d86.js +1 -0
- package/.next/static/chunks/app/(app)/routines/page-bcc55550b197a9fa.js +1 -0
- package/.next/static/chunks/app/(app)/search/page-5c5f67558d0dbf0d.js +1 -0
- package/.next/static/chunks/app/(app)/security/page-a7d41e36aa366b45.js +1 -0
- package/.next/static/chunks/app/(app)/skills/page-c5b21e89593b8336.js +1 -0
- package/.next/static/chunks/app/(app)/tasks/page-08ae079e3e54d2ce.js +1 -0
- package/.next/static/chunks/app/(app)/test-dev/page-633f82dfd9c3ce23.js +1 -0
- package/.next/static/chunks/app/(app)/update/page-4be019054351bfac.js +1 -0
- package/.next/static/chunks/app/(auth)/login/page-6e85d3377062acae.js +1 -0
- package/.next/static/chunks/app/(auth)/onboarding/page-ebb10c175abf3b85.js +1 -0
- package/.next/static/chunks/app/_global-error/page-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/_not-found/page-dc38b02aebeab535.js +1 -0
- package/.next/static/chunks/app/api/auth/[...all]/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/cron/tick/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/dev-login/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/locks/acquire/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/models/progress/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/passkey/authenticate/options/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/passkey/authenticate/verify/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/passkey/register/options/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/passkey/register/verify/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/stream/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/sync/file/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/telegram/poll/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/upload/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/api/v1/[[...path]]/route-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/app/error-09899a13c38b6e89.js +1 -0
- package/.next/static/chunks/app/global-error-b8050d4d886f448c.js +1 -0
- package/.next/static/chunks/app/layout-ab9deed1e7e2e9df.js +1 -0
- package/.next/static/chunks/framework-4b2c6b6043dd203f.js +1 -0
- package/.next/static/chunks/main-722e16032e7764d1.js +5 -0
- package/.next/static/chunks/main-app-761880af2b6f1962.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-23fe50a6bf589c97.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-222e3894b78c67db.js +1 -0
- package/.next/static/css/0a9b5805594444e3.css +1 -0
- package/.next/static/yztMvBwyrWWkSqP6jfXoa/_buildManifest.js +1 -0
- package/.next/static/yztMvBwyrWWkSqP6jfXoa/_ssgManifest.js +1 -0
- package/.next/trace-build +1 -0
- package/.next/types/app/(app)/activity/page.ts +87 -0
- package/.next/types/app/(app)/agents/[handle]/page.ts +87 -0
- package/.next/types/app/(app)/code/page.ts +87 -0
- package/.next/types/app/(app)/config/page.ts +87 -0
- package/.next/types/app/(app)/costs/page.ts +87 -0
- package/.next/types/app/(app)/cron/page.ts +87 -0
- package/.next/types/app/(app)/dashboard/page.ts +87 -0
- package/.next/types/app/(app)/docs/[id]/page.ts +87 -0
- package/.next/types/app/(app)/docs/page.ts +87 -0
- package/.next/types/app/(app)/github/page.ts +87 -0
- package/.next/types/app/(app)/goals/page.ts +87 -0
- package/.next/types/app/(app)/inbox/page.ts +87 -0
- package/.next/types/app/(app)/knowledge/page.ts +87 -0
- package/.next/types/app/(app)/models/page.ts +87 -0
- package/.next/types/app/(app)/notifications/page.ts +87 -0
- package/.next/types/app/(app)/org/page.ts +87 -0
- package/.next/types/app/(app)/organizations/page.ts +87 -0
- package/.next/types/app/(app)/page.ts +87 -0
- package/.next/types/app/(app)/planner/page.ts +87 -0
- package/.next/types/app/(app)/plugins/page.ts +87 -0
- package/.next/types/app/(app)/pm/page.ts +87 -0
- package/.next/types/app/(app)/prepare-deploy/page.ts +87 -0
- package/.next/types/app/(app)/profile/page.ts +87 -0
- package/.next/types/app/(app)/pulse/page.ts +87 -0
- package/.next/types/app/(app)/reports/[id]/page.ts +87 -0
- package/.next/types/app/(app)/reports/page.ts +87 -0
- package/.next/types/app/(app)/routines/page.ts +87 -0
- package/.next/types/app/(app)/search/page.ts +87 -0
- package/.next/types/app/(app)/security/page.ts +87 -0
- package/.next/types/app/(app)/skills/page.ts +87 -0
- package/.next/types/app/(app)/tasks/page.ts +87 -0
- package/.next/types/app/(app)/test-dev/page.ts +87 -0
- package/.next/types/app/(app)/update/page.ts +87 -0
- package/.next/types/app/(auth)/login/page.ts +87 -0
- package/.next/types/app/(auth)/onboarding/page.ts +87 -0
- package/.next/types/app/api/auth/[...all]/route.ts +351 -0
- package/.next/types/app/api/cron/tick/route.ts +351 -0
- package/.next/types/app/api/dev-login/route.ts +351 -0
- package/.next/types/app/api/locks/acquire/route.ts +351 -0
- package/.next/types/app/api/models/progress/route.ts +351 -0
- package/.next/types/app/api/passkey/authenticate/options/route.ts +351 -0
- package/.next/types/app/api/passkey/authenticate/verify/route.ts +351 -0
- package/.next/types/app/api/passkey/register/options/route.ts +351 -0
- package/.next/types/app/api/passkey/register/verify/route.ts +351 -0
- package/.next/types/app/api/stream/route.ts +351 -0
- package/.next/types/app/api/sync/file/route.ts +351 -0
- package/.next/types/app/api/telegram/poll/route.ts +351 -0
- package/.next/types/app/api/upload/route.ts +351 -0
- package/.next/types/app/api/v1/[[...path]]/route.ts +351 -0
- package/.next/types/cache-life.d.ts +145 -0
- package/.next/types/link.d.ts +210 -0
- package/.next/types/package.json +1 -0
- package/.next/types/routes.d.ts +120 -0
- package/.next/types/validator.ts +511 -0
- package/CHANGELOG.md +312 -0
- package/LICENSE +21 -0
- package/README.md +382 -0
- package/README.pt-BR.md +391 -0
- package/bin/constella.mjs +329 -0
- package/bin/guard-hook.mjs +44 -0
- package/bin/lock-hook.mjs +49 -0
- package/bin/worker.mjs +142 -0
- package/docs/assets/arch-orbit.svg +56 -0
- package/docs/assets/blackhole.svg +37 -0
- package/docs/assets/divider-orbit.svg +23 -0
- package/docs/assets/hero-constella.svg +72 -0
- package/docs/en/AGENTS.md +279 -0
- package/docs/en/AI_ARCHITECTURE.md +373 -0
- package/docs/en/ARCHITECTURE.md +334 -0
- package/docs/en/AUTH_MODE.md +247 -0
- package/docs/en/CHAT_COMMANDS.md +305 -0
- package/docs/en/CONFIGURATION.md +340 -0
- package/docs/en/DEPLOY.md +331 -0
- package/docs/en/DM.md +297 -0
- package/docs/en/FAQ.md +258 -0
- package/docs/en/GITHUB.md +341 -0
- package/docs/en/GOALS_SPECS_ISSUES.md +303 -0
- package/docs/en/INBOX.md +340 -0
- package/docs/en/INSTALLATION.md +329 -0
- package/docs/en/KB_AGENT.md +305 -0
- package/docs/en/KB_RAG.md +356 -0
- package/docs/en/MCP.md +313 -0
- package/docs/en/MEMORY_RAG.md +289 -0
- package/docs/en/MODELS.md +341 -0
- package/docs/en/ONBOARDING.md +327 -0
- package/docs/en/PLUGINS.md +290 -0
- package/docs/en/PORTABLE_MODE.md +387 -0
- package/docs/en/PO_AGENT.md +379 -0
- package/docs/en/PREPARE_DEPLOY.md +308 -0
- package/docs/en/PROJECT_STACKS.md +258 -0
- package/docs/en/PUBLIC_API.md +315 -0
- package/docs/en/PUBLISHING.md +343 -0
- package/docs/en/README.md +95 -0
- package/docs/en/SECURITY.md +280 -0
- package/docs/en/SKILLS.md +349 -0
- package/docs/en/START_MODE.md +340 -0
- package/docs/en/SYNCED_BLOCKS.md +320 -0
- package/docs/en/TEAM_ROOM.md +285 -0
- package/docs/en/TELEGRAM.md +294 -0
- package/docs/en/TEST_DEV.md +321 -0
- package/docs/en/TROUBLESHOOTING.md +294 -0
- package/docs/en/UPDATE.md +301 -0
- package/docs/en/VPS_MODE.md +334 -0
- package/docs/en/WORKFLOW.md +321 -0
- package/docs/pt/AGENTS.md +279 -0
- package/docs/pt/AI_ARCHITECTURE.md +373 -0
- package/docs/pt/ARCHITECTURE.md +334 -0
- package/docs/pt/AUTH_MODE.md +247 -0
- package/docs/pt/CHAT_COMMANDS.md +307 -0
- package/docs/pt/CONFIGURATION.md +340 -0
- package/docs/pt/DEPLOY.md +331 -0
- package/docs/pt/DM.md +297 -0
- package/docs/pt/FAQ.md +258 -0
- package/docs/pt/GITHUB.md +341 -0
- package/docs/pt/GOALS_SPECS_ISSUES.md +303 -0
- package/docs/pt/INBOX.md +340 -0
- package/docs/pt/INSTALLATION.md +329 -0
- package/docs/pt/KB_AGENT.md +305 -0
- package/docs/pt/KB_RAG.md +356 -0
- package/docs/pt/MCP.md +313 -0
- package/docs/pt/MEMORY_RAG.md +289 -0
- package/docs/pt/MODELS.md +341 -0
- package/docs/pt/ONBOARDING.md +327 -0
- package/docs/pt/PLUGINS.md +290 -0
- package/docs/pt/PORTABLE_MODE.md +387 -0
- package/docs/pt/PO_AGENT.md +379 -0
- package/docs/pt/PREPARE_DEPLOY.md +308 -0
- package/docs/pt/PROJECT_STACKS.md +258 -0
- package/docs/pt/PUBLIC_API.md +315 -0
- package/docs/pt/PUBLISHING.md +343 -0
- package/docs/pt/README.md +95 -0
- package/docs/pt/SECURITY.md +280 -0
- package/docs/pt/SKILLS.md +349 -0
- package/docs/pt/START_MODE.md +340 -0
- package/docs/pt/SYNCED_BLOCKS.md +320 -0
- package/docs/pt/TEAM_ROOM.md +285 -0
- package/docs/pt/TELEGRAM.md +294 -0
- package/docs/pt/TEST_DEV.md +321 -0
- package/docs/pt/TROUBLESHOOTING.md +294 -0
- package/docs/pt/UPDATE.md +301 -0
- package/docs/pt/VPS_MODE.md +334 -0
- package/docs/pt/WORKFLOW.md +321 -0
- package/drizzle/0000_regular_nightshade.sql +644 -0
- package/drizzle/0001_mixed_zombie.sql +106 -0
- package/drizzle/meta/0000_snapshot.json +4650 -0
- package/drizzle/meta/0001_snapshot.json +5418 -0
- package/drizzle/meta/_journal.json +20 -0
- package/drizzle.config.mjs +16 -0
- package/next.config.mjs +18 -0
- package/package.json +130 -0
- package/scripts/clean-repo.mjs +20 -0
- package/scripts/dev-all.mjs +46 -0
- package/scripts/i18n-parity.mjs +57 -0
- package/scripts/mcp-server.mjs +100 -0
- package/scripts/postbuild.mjs +11 -0
- package/scripts/publish-public.mjs +116 -0
- package/scripts/start-all.mjs +45 -0
- package/scripts/trim-next.mjs +23 -0
- package/scripts/vps-install.sh +39 -0
- package/skills/CONTRIBUTING.md +122 -0
- package/skills/COVERAGE.md +129 -0
- package/skills/INDEX.json +3443 -0
- package/skills/README.md +57 -0
- package/skills/design/animation-motion/SKILL.md +60 -0
- package/skills/design/color-and-typography/SKILL.md +60 -0
- package/skills/design/css-techniques/SKILL.md +58 -0
- package/skills/design/design-systems/SKILL.md +60 -0
- package/skills/design/gradients/SKILL.md +59 -0
- package/skills/design/graphic-design-basics/SKILL.md +55 -0
- package/skills/design/microinteractions/SKILL.md +58 -0
- package/skills/design/responsive-layout/SKILL.md +59 -0
- package/skills/design/ui-ux-principles/SKILL.md +58 -0
- package/skills/engineering/architecture/api-design-rest-graphql/SKILL.md +67 -0
- package/skills/engineering/architecture/caching-strategies/SKILL.md +59 -0
- package/skills/engineering/architecture/data-modeling/SKILL.md +64 -0
- package/skills/engineering/architecture/message-queues-async/SKILL.md +58 -0
- package/skills/engineering/architecture/scalability-reliability/SKILL.md +62 -0
- package/skills/engineering/architecture/software-architecture-patterns/SKILL.md +56 -0
- package/skills/engineering/architecture/system-design-fundamentals/SKILL.md +56 -0
- package/skills/engineering/backend/auth-and-authorization/SKILL.md +62 -0
- package/skills/engineering/backend/backend-fundamentals/SKILL.md +65 -0
- package/skills/engineering/backend/observability-logging/SKILL.md +60 -0
- package/skills/engineering/frontend/accessibility-wcag/SKILL.md +57 -0
- package/skills/engineering/frontend/frontend-architecture/SKILL.md +65 -0
- package/skills/engineering/frontend/rendering-strategies-ssr-csr/SKILL.md +60 -0
- package/skills/engineering/frontend/state-management/SKILL.md +69 -0
- package/skills/engineering/performance/backend-performance/SKILL.md +69 -0
- package/skills/engineering/performance/database-query-optimization/SKILL.md +64 -0
- package/skills/engineering/performance/profiling-and-benchmarking/SKILL.md +60 -0
- package/skills/engineering/performance/web-performance-core-vitals/SKILL.md +72 -0
- package/skills/engineering/practices/clean-code/SKILL.md +61 -0
- package/skills/engineering/practices/code-optimization/SKILL.md +60 -0
- package/skills/engineering/practices/code-review-practices/SKILL.md +58 -0
- package/skills/engineering/practices/git-workflow/SKILL.md +62 -0
- package/skills/engineering/practices/refactoring/SKILL.md +58 -0
- package/skills/engineering/security/appsec-fundamentals/SKILL.md +70 -0
- package/skills/engineering/security/dependency-supply-chain/SKILL.md +77 -0
- package/skills/engineering/security/owasp-asvs/SKILL.md +54 -0
- package/skills/engineering/security/owasp-top-10/SKILL.md +63 -0
- package/skills/engineering/security/secrets-management/SKILL.md +58 -0
- package/skills/engineering/security/secure-auth-sessions/SKILL.md +56 -0
- package/skills/engineering/testing/tdd-and-coverage/SKILL.md +62 -0
- package/skills/engineering/testing/testing-strategy-pyramid/SKILL.md +56 -0
- package/skills/engineering/testing/unit-integration-e2e/SKILL.md +75 -0
- package/skills/languages/c/SKILL.md +74 -0
- package/skills/languages/clojure/SKILL.md +73 -0
- package/skills/languages/cpp/SKILL.md +75 -0
- package/skills/languages/csharp/SKILL.md +75 -0
- package/skills/languages/dart/SKILL.md +82 -0
- package/skills/languages/elixir/SKILL.md +74 -0
- package/skills/languages/erlang/SKILL.md +76 -0
- package/skills/languages/go/SKILL.md +83 -0
- package/skills/languages/haskell/SKILL.md +70 -0
- package/skills/languages/java/SKILL.md +71 -0
- package/skills/languages/javascript/SKILL.md +62 -0
- package/skills/languages/kotlin/SKILL.md +68 -0
- package/skills/languages/lua/SKILL.md +79 -0
- package/skills/languages/objectivec/SKILL.md +83 -0
- package/skills/languages/php/SKILL.md +74 -0
- package/skills/languages/python/SKILL.md +68 -0
- package/skills/languages/r/SKILL.md +70 -0
- package/skills/languages/ruby/SKILL.md +67 -0
- package/skills/languages/rust/SKILL.md +72 -0
- package/skills/languages/scala/SKILL.md +73 -0
- package/skills/languages/swift/SKILL.md +73 -0
- package/skills/languages/typescript/SKILL.md +69 -0
- package/skills/meta/authoring-agent-skills/SKILL.md +73 -0
- package/skills/meta/progressive-disclosure/SKILL.md +65 -0
- package/skills/meta/skill-frontmatter-spec/SKILL.md +65 -0
- package/skills/process/adr-technical-decisions/SKILL.md +59 -0
- package/skills/process/app-planning/SKILL.md +63 -0
- package/skills/process/architecture-before-code/SKILL.md +52 -0
- package/skills/process/breaking-work-into-sprints/SKILL.md +53 -0
- package/skills/process/idea-to-product/SKILL.md +50 -0
- package/skills/process/mocks-and-screen-flows/SKILL.md +52 -0
- package/skills/process/prioritization-moscow-rice/SKILL.md +64 -0
- package/skills/process/problem-framing/SKILL.md +51 -0
- package/skills/process/product-discovery/SKILL.md +53 -0
- package/skills/process/readme-generation/SKILL.md +90 -0
- package/skills/process/requirements-to-specs/SKILL.md +53 -0
- package/skills/process/research-official-docs/SKILL.md +58 -0
- package/skills/process/review-code-perf-security/SKILL.md +65 -0
- package/skills/process/security-by-design/SKILL.md +68 -0
- package/skills/process/specs-to-issues/SKILL.md +53 -0
- package/skills/process/testing-before-done/SKILL.md +61 -0
- package/skills/process/validating-ux-navigation/SKILL.md +63 -0
- package/skills/references/ai-attachments-ui/SKILL.md +66 -0
- package/skills/references/ai-in-browser-webllm/SKILL.md +74 -0
- package/skills/references/ai-tool-ui-patterns/SKILL.md +63 -0
- package/skills/references/component-patterns-gallery/SKILL.md +62 -0
- package/skills/references/gradient-resources/SKILL.md +66 -0
- package/skills/references/react-component-libraries/SKILL.md +61 -0
- package/skills/references/saas-landing-patterns/SKILL.md +67 -0
- package/skills/references/shadcn-tailwind-theming/SKILL.md +74 -0
- package/skills/references/vercel-ai-sdk-elements/SKILL.md +66 -0
- package/skills/references/web-animation-codrops/SKILL.md +68 -0
- package/skills/stacks/aiml/jupyter/SKILL.md +68 -0
- package/skills/stacks/aiml/keras/SKILL.md +77 -0
- package/skills/stacks/aiml/numpy/SKILL.md +69 -0
- package/skills/stacks/aiml/pandas/SKILL.md +72 -0
- package/skills/stacks/aiml/pytorch/SKILL.md +77 -0
- package/skills/stacks/aiml/scikit-learn/SKILL.md +74 -0
- package/skills/stacks/aiml/tensorflow/SKILL.md +79 -0
- package/skills/stacks/auth/auth0/SKILL.md +63 -0
- package/skills/stacks/auth/authjs/SKILL.md +69 -0
- package/skills/stacks/auth/clerk/SKILL.md +72 -0
- package/skills/stacks/auth/keycloak/SKILL.md +63 -0
- package/skills/stacks/auth/lucia/SKILL.md +56 -0
- package/skills/stacks/auth/passport/SKILL.md +70 -0
- package/skills/stacks/auth/supabase-auth/SKILL.md +66 -0
- package/skills/stacks/baas/amplify/SKILL.md +71 -0
- package/skills/stacks/baas/appwrite/SKILL.md +79 -0
- package/skills/stacks/baas/firebase/SKILL.md +73 -0
- package/skills/stacks/baas/heroku/SKILL.md +71 -0
- package/skills/stacks/backend/actix/SKILL.md +77 -0
- package/skills/stacks/backend/adonisjs/SKILL.md +65 -0
- package/skills/stacks/backend/aspnet-core/SKILL.md +75 -0
- package/skills/stacks/backend/codeigniter/SKILL.md +76 -0
- package/skills/stacks/backend/django/SKILL.md +62 -0
- package/skills/stacks/backend/express/SKILL.md +65 -0
- package/skills/stacks/backend/fastapi/SKILL.md +64 -0
- package/skills/stacks/backend/fastify/SKILL.md +64 -0
- package/skills/stacks/backend/fiber/SKILL.md +68 -0
- package/skills/stacks/backend/flask/SKILL.md +71 -0
- package/skills/stacks/backend/gin/SKILL.md +68 -0
- package/skills/stacks/backend/graphql/SKILL.md +70 -0
- package/skills/stacks/backend/hono/SKILL.md +64 -0
- package/skills/stacks/backend/koa/SKILL.md +63 -0
- package/skills/stacks/backend/laravel/SKILL.md +73 -0
- package/skills/stacks/backend/nestjs/SKILL.md +70 -0
- package/skills/stacks/backend/nginx/SKILL.md +77 -0
- package/skills/stacks/backend/phoenix/SKILL.md +68 -0
- package/skills/stacks/backend/rails/SKILL.md +67 -0
- package/skills/stacks/backend/spring/SKILL.md +70 -0
- package/skills/stacks/backend/spring-boot/SKILL.md +70 -0
- package/skills/stacks/backend/symfony/SKILL.md +77 -0
- package/skills/stacks/container/containerd/SKILL.md +75 -0
- package/skills/stacks/container/docker/SKILL.md +90 -0
- package/skills/stacks/container/podman/SKILL.md +93 -0
- package/skills/stacks/database/cassandra/SKILL.md +74 -0
- package/skills/stacks/database/cockroachdb/SKILL.md +69 -0
- package/skills/stacks/database/dynamodb/SKILL.md +62 -0
- package/skills/stacks/database/mariadb/SKILL.md +71 -0
- package/skills/stacks/database/mongodb/SKILL.md +71 -0
- package/skills/stacks/database/mysql/SKILL.md +72 -0
- package/skills/stacks/database/neon/SKILL.md +68 -0
- package/skills/stacks/database/planetscale/SKILL.md +70 -0
- package/skills/stacks/database/postgresql/SKILL.md +81 -0
- package/skills/stacks/database/redis/SKILL.md +78 -0
- package/skills/stacks/database/sqlite/SKILL.md +70 -0
- package/skills/stacks/database/supabase/SKILL.md +79 -0
- package/skills/stacks/dataviz/chart-js/SKILL.md +72 -0
- package/skills/stacks/dataviz/d3/SKILL.md +77 -0
- package/skills/stacks/dataviz/grafana/SKILL.md +69 -0
- package/skills/stacks/dataviz/plotly/SKILL.md +71 -0
- package/skills/stacks/frontend/alpine/SKILL.md +75 -0
- package/skills/stacks/frontend/angular/SKILL.md +75 -0
- package/skills/stacks/frontend/backbone/SKILL.md +82 -0
- package/skills/stacks/frontend/ember/SKILL.md +85 -0
- package/skills/stacks/frontend/htmx/SKILL.md +73 -0
- package/skills/stacks/frontend/lit/SKILL.md +76 -0
- package/skills/stacks/frontend/preact/SKILL.md +74 -0
- package/skills/stacks/frontend/qwik/SKILL.md +65 -0
- package/skills/stacks/frontend/react/SKILL.md +77 -0
- package/skills/stacks/frontend/solidjs/SKILL.md +75 -0
- package/skills/stacks/frontend/svelte/SKILL.md +70 -0
- package/skills/stacks/frontend/vue/SKILL.md +69 -0
- package/skills/stacks/infra/ansible/SKILL.md +76 -0
- package/skills/stacks/infra/aws/SKILL.md +66 -0
- package/skills/stacks/infra/azure/SKILL.md +72 -0
- package/skills/stacks/infra/circleci/SKILL.md +78 -0
- package/skills/stacks/infra/cloudflare/SKILL.md +65 -0
- package/skills/stacks/infra/fly-io/SKILL.md +63 -0
- package/skills/stacks/infra/gcp/SKILL.md +66 -0
- package/skills/stacks/infra/jenkins/SKILL.md +73 -0
- package/skills/stacks/infra/kubernetes/SKILL.md +64 -0
- package/skills/stacks/infra/netlify/SKILL.md +60 -0
- package/skills/stacks/infra/railway/SKILL.md +63 -0
- package/skills/stacks/infra/tailscale/SKILL.md +65 -0
- package/skills/stacks/infra/terraform/SKILL.md +75 -0
- package/skills/stacks/infra/vagrant/SKILL.md +70 -0
- package/skills/stacks/infra/vercel/SKILL.md +60 -0
- package/skills/stacks/meta/astro/SKILL.md +64 -0
- package/skills/stacks/meta/docusaurus/SKILL.md +71 -0
- package/skills/stacks/meta/eleventy/SKILL.md +69 -0
- package/skills/stacks/meta/gatsby/SKILL.md +63 -0
- package/skills/stacks/meta/hugo/SKILL.md +73 -0
- package/skills/stacks/meta/jekyll/SKILL.md +70 -0
- package/skills/stacks/meta/nextjs/SKILL.md +62 -0
- package/skills/stacks/meta/nuxt/SKILL.md +66 -0
- package/skills/stacks/meta/remix/SKILL.md +67 -0
- package/skills/stacks/meta/sveltekit/SKILL.md +70 -0
- package/skills/stacks/meta/vite/SKILL.md +63 -0
- package/skills/stacks/mobile/android/SKILL.md +77 -0
- package/skills/stacks/mobile/flutter/SKILL.md +77 -0
- package/skills/stacks/mobile/ionic/SKILL.md +72 -0
- package/skills/stacks/mobile/nativescript/SKILL.md +71 -0
- package/skills/stacks/mobile/react-native/SKILL.md +75 -0
- package/skills/stacks/mobile/xamarin/SKILL.md +73 -0
- package/skills/stacks/orm/diesel/SKILL.md +72 -0
- package/skills/stacks/orm/django-orm/SKILL.md +58 -0
- package/skills/stacks/orm/drizzle/SKILL.md +67 -0
- package/skills/stacks/orm/gorm/SKILL.md +73 -0
- package/skills/stacks/orm/knex/SKILL.md +64 -0
- package/skills/stacks/orm/mongoose/SKILL.md +64 -0
- package/skills/stacks/orm/prisma/SKILL.md +64 -0
- package/skills/stacks/orm/sequelize/SKILL.md +65 -0
- package/skills/stacks/orm/sqlalchemy/SKILL.md +71 -0
- package/skills/stacks/orm/typeorm/SKILL.md +70 -0
- package/skills/stacks/queue/bullmq/SKILL.md +69 -0
- package/skills/stacks/queue/celery/SKILL.md +68 -0
- package/skills/stacks/queue/kafka/SKILL.md +66 -0
- package/skills/stacks/queue/nats/SKILL.md +66 -0
- package/skills/stacks/queue/rabbitmq/SKILL.md +64 -0
- package/skills/stacks/queue/redis/SKILL.md +66 -0
- package/skills/stacks/runtime/beam/SKILL.md +72 -0
- package/skills/stacks/runtime/bun/SKILL.md +80 -0
- package/skills/stacks/runtime/deno/SKILL.md +74 -0
- package/skills/stacks/runtime/dotnet/SKILL.md +64 -0
- package/skills/stacks/runtime/jvm/SKILL.md +66 -0
- package/skills/stacks/runtime/node/SKILL.md +70 -0
- package/skills/stacks/runtime/pypy/SKILL.md +69 -0
- package/skills/stacks/runtime/python3/SKILL.md +70 -0
- package/skills/stacks/styling/bootstrap/SKILL.md +74 -0
- package/skills/stacks/styling/bulma/SKILL.md +80 -0
- package/skills/stacks/styling/chakra-ui/SKILL.md +61 -0
- package/skills/stacks/styling/css-modules/SKILL.md +54 -0
- package/skills/stacks/styling/mui/SKILL.md +60 -0
- package/skills/stacks/styling/sass/SKILL.md +63 -0
- package/skills/stacks/styling/shadcn-ui/SKILL.md +58 -0
- package/skills/stacks/styling/styled-components/SKILL.md +62 -0
- package/skills/stacks/styling/tailwind/SKILL.md +59 -0
- package/skills/stacks/styling/unocss/SKILL.md +64 -0
- package/skills/stacks/styling/vanilla-extract/SKILL.md +64 -0
- package/skills/stacks/styling/vuetify/SKILL.md +89 -0
- package/skills/stacks/testing/cypress/SKILL.md +68 -0
- package/skills/stacks/testing/jasmine/SKILL.md +67 -0
- package/skills/stacks/testing/jest/SKILL.md +67 -0
- package/skills/stacks/testing/mocha/SKILL.md +71 -0
- package/skills/stacks/testing/playwright/SKILL.md +68 -0
- package/skills/stacks/testing/puppeteer/SKILL.md +70 -0
- package/skills/stacks/testing/selenium/SKILL.md +70 -0
- package/skills/stacks/testing/vitest/SKILL.md +68 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
[β Docs index](./README.md) Β· [π§π· PortuguΓͺs](../pt/ARCHITECTURE.md) Β· [β¦ Constella](../../README.md)
|
|
2
|
+
|
|
3
|
+
# π Architecture β the central ship
|
|
4
|
+
|
|
5
|
+
Constella is a local-first control plane: a single Node process supervises a **web server** and a **24/7 worker**, both orbiting one runtime root on disk where every organization keeps an isolated workspace. The directory is the source of truth; SQLite is the index that lets the UI and search agree.
|
|
6
|
+
|
|
7
|
+
> β¦ This document maps the *structural* layer: process topology, runtime root + org isolation, the filesystem jail, the SQLite/Drizzle store, the sync engine + file-watcher, and the cron tick that drives autonomous work. For the *cognitive* layer (how agents think, RAG, KB) see [AI_ARCHITECTURE](./AI_ARCHITECTURE.md).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## π°οΈ When to use this doc
|
|
12
|
+
|
|
13
|
+
- You need to understand **how Constella boots** and which process does what.
|
|
14
|
+
- You are debugging **why a file edit did not appear** in the UI (sync engine).
|
|
15
|
+
- You are reasoning about **multi-tenant isolation** (one runtime root, many orgs).
|
|
16
|
+
- You are hardening or auditing the **worker β web** trust boundary.
|
|
17
|
+
- You want the **table-level map** of the database (`src/db/schema.ts`).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## π How it works (high level)
|
|
22
|
+
|
|
23
|
+
A single launcher β `bin/constella.mjs` β resolves the run mode, prepares the runtime root and secrets, applies the database migrations, then **supervises two long-lived children**:
|
|
24
|
+
|
|
25
|
+
| Child | Entry | Role |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| **web** | `next start -H <host> -p <port>` (from `PKG_ROOT`) | The Next.js 16 app: UI, server actions, all `/api` routes, agent orchestration. |
|
|
28
|
+
| **worker** | `bin/worker.mjs` | Headless 24/7 driver: cron tick, the chokidar file-watcher, the Telegram long-poll. Talks to the web over loopback HTTP. |
|
|
29
|
+
|
|
30
|
+
The worker never touches the database directly. It only makes authenticated HTTP calls back into the web server (`x-worker-secret`), so all writes funnel through one process and one set of server actions. This keeps the trust boundary small and the DB single-writer.
|
|
31
|
+
|
|
32
|
+
```mermaid
|
|
33
|
+
flowchart TB
|
|
34
|
+
subgraph Launcher["bin/constella.mjs (supervisor)"]
|
|
35
|
+
SUP["supervise(): restart on crash<br/>max 5 / 60s"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
SUP -->|spawn| WEB["web<br/>next start @ host:port<br/>cwd = PKG_ROOT"]
|
|
39
|
+
SUP -->|spawn| WK["worker<br/>bin/worker.mjs"]
|
|
40
|
+
|
|
41
|
+
WK -->|"POST /api/cron/tick<br/>(x-worker-secret)"| WEB
|
|
42
|
+
WK -->|"POST /api/sync/file<br/>(x-worker-secret)"| WEB
|
|
43
|
+
WK -->|"POST /api/telegram/poll"| WEB
|
|
44
|
+
WK -->|"chokidar watch"| DISK[("Runtime root<br/>~/.constella")]
|
|
45
|
+
|
|
46
|
+
WEB -->|drizzle / better-sqlite3| DB[("constella.db<br/>WAL")]
|
|
47
|
+
WEB -->|"fs-workspace safe()"| DISK
|
|
48
|
+
WEB -->|spawn claude / codex| CLI["agent CLIs<br/>cwd = org workspace (FS jail)"]
|
|
49
|
+
CLI -->|edit files| DISK
|
|
50
|
+
|
|
51
|
+
classDef store fill:#1a1a2e,stroke:#e0a44e,color:#fff
|
|
52
|
+
class DB,DISK store
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## π Main flow β boot to steady state
|
|
58
|
+
|
|
59
|
+
The launcher's boot sequence (`bin/constella.mjs`), in order:
|
|
60
|
+
|
|
61
|
+
1. **Resolve run mode** β explicit flag (`--start|--auth|--vps|--portable`) wins, then legacy `--bind`, default `start`. See [START_MODE](./START_MODE.md), [AUTH_MODE](./AUTH_MODE.md), [VPS_MODE](./VPS_MODE.md), [PORTABLE_MODE](./PORTABLE_MODE.md).
|
|
62
|
+
2. **Resolve the runtime root** β `CONSTELLA_HOME` / `--path` wins; otherwise `~/.constella`. Portable mode with no path enumerates removable USB drives and prompts. `mkdir -p <HOME>/organizations`.
|
|
63
|
+
3. **Pin paths** β `DATABASE_URL=file:<HOME>/constella.db`, `CONSTELLA_PKG_ROOT=<install dir>`. `PKG_ROOT` is where the prebuilt `.next`, `drizzle/` migrations and configs live (not the launch dir).
|
|
64
|
+
4. **Persist secrets** β read/generate `BETTER_AUTH_SECRET`, `CONSTELLA_VAULT_KEY`, `CONSTELLA_WORKER_SECRET` and write them to `<HOME>/.env` with mode `0o600`. Generated once; reused across restarts so sessions + the encrypted vault survive.
|
|
65
|
+
5. **Portable disk check** β refuse `< 32 GB` free (fatal); `β₯ 32 GB` is fine.
|
|
66
|
+
6. **Apply migrations** β `drizzle-kit migrate --config drizzle.config.mjs` from `PKG_ROOT`. Idempotent. A *fresh* DB that fails to migrate aborts the boot (no tables β every request 500s).
|
|
67
|
+
7. **Build-on-first-run (fallback only)** β the published package ships a prebuilt `.next`, so this is skipped. From a source tree without a build it runs `next build`; it refuses to silently fall back to `next dev` in a public run unless `CONSTELLA_DEV=1`.
|
|
68
|
+
8. **Supervise web + worker** β spawn the web server, then ~1.5 s later the worker (so Next has a head start). Each child is wrapped in `supervise()`; on an unexpected exit it auto-restarts (bounded: `MAX_RESTARTS = 5` within `WINDOW_MS = 60_000`), else the supervisor gives up and exits.
|
|
69
|
+
|
|
70
|
+
Once steady, the **worker** waits for the server to answer (`waitForServer`, up to ~90 s), then:
|
|
71
|
+
|
|
72
|
+
- Fires the **cron tick** immediately and every `INTERVAL` (`CONSTELLA_WORKER_INTERVAL_MS`, default `60_000` ms).
|
|
73
|
+
- Starts the **chokidar watcher** over `<HOME>/organizations`.
|
|
74
|
+
- Runs the **Telegram long-poll** loop (`getUpdates` waits ~25 s server-side; gap ~1 s between polls).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## πͺ Key concepts
|
|
79
|
+
|
|
80
|
+
### Runtime root + per-org isolation
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
~/.constella/ β runtime root (CONSTELLA_HOME or --path)
|
|
84
|
+
ββ .env β persisted secrets (mode 0600)
|
|
85
|
+
ββ constella.db β SQLite (WAL) β the index
|
|
86
|
+
ββ cache/ β models.dev cache, etc.
|
|
87
|
+
ββ backups/ β .env + db backups on update
|
|
88
|
+
ββ organizations/
|
|
89
|
+
ββ <orgId>/
|
|
90
|
+
ββ workspace/ β the org's isolated, sandboxed tree
|
|
91
|
+
ββ .claude/ β agents/, skills/, BRIEF.md (config INSIDE the workspace)
|
|
92
|
+
ββ DOCS/ PO/ Reports/
|
|
93
|
+
ββ specs/ issues/ mock/
|
|
94
|
+
ββ uploads/ β operator attachments, Telegram media
|
|
95
|
+
ββ <the product the agents build>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The workspace directory is keyed by the **stable `organization.id`** (never the renameable slug). A one-time boot migration renames a legacy `constella/` dir to `workspace/` so existing orgs keep their data (falling back to a copy on a cross-device move, never deleting the legacy dir).
|
|
99
|
+
|
|
100
|
+
### The filesystem jail β `safe()`
|
|
101
|
+
|
|
102
|
+
Every workspace read/write goes through `safe(root, rel)` in `src/lib/fs-workspace.ts`. It is the single chokepoint that keeps a prompt-injected agent (or a buggy path) inside its own org:
|
|
103
|
+
|
|
104
|
+
1. **Lexical check** β `normalize(join(root, rel))` must equal `root` or start with `root + sep`. Because `join` re-roots absolute, drive-letter and UNC paths under `root`, this blocks `../`, absolute escapes and Windows drive tricks.
|
|
105
|
+
2. **Symlink check** β it resolves the real path of the nearest existing ancestor (`realAncestor`) and re-verifies it is still under the real `root`. This defeats a symlink *planted inside* the workspace that would otherwise tunnel out to another org or the wider filesystem.
|
|
106
|
+
|
|
107
|
+
`orgRoot()` additionally validates the org id (`/^[A-Za-z0-9_-]{6,64}$/`) before it ever touches a path, so a malformed id can't traverse. Heavy build/dependency dirs (`node_modules`, `.git`, `.next`, `dist`, `.testdev`, β¦) are skipped by `listFiles()` via `HEAVY_DIRS`.
|
|
108
|
+
|
|
109
|
+
### Directory is truth, DB is the index
|
|
110
|
+
|
|
111
|
+
The filesystem is canonical; the database **mirrors** it. Indexers in `src/server/sync.ts` are idempotent upserts and **disk always wins on conflict**. The same file written by an agent and later re-indexed by the watcher updates *one* row (keyed by H1 title or relative path), never duplicates.
|
|
112
|
+
|
|
113
|
+
### SQLite + Drizzle
|
|
114
|
+
|
|
115
|
+
`src/db/index.ts` opens `better-sqlite3` against the resolved `DATABASE_URL`, sets `journal_mode = WAL` and `foreign_keys = ON`, and wraps it with `drizzle-orm`. It also exports the raw `sqlite` handle for **migration-free boot DDL** (`CREATE TABLE IF NOT EXISTS` + guarded `ALTER ADD COLUMN`) β used to add tables/columns to existing DBs *without* `drizzle-kit push`, which would drift this project's migration history. See [SECURITY](./SECURITY.md) and [TROUBLESHOOTING](./TROUBLESHOOTING.md) for the `db:push` caveat.
|
|
116
|
+
|
|
117
|
+
### Worker β web trust boundary
|
|
118
|
+
|
|
119
|
+
The worker holds the privileged `CONSTELLA_WORKER_SECRET` and attaches it as `x-worker-secret` to every call. Two protections matter:
|
|
120
|
+
|
|
121
|
+
- **Fail closed on the server**: `/api/cron/tick` and `/api/sync/file` return `401` unless the header equals the configured secret. An unset secret does **not** leave them open β they reject everyone.
|
|
122
|
+
- **SSRF / exfil guard on the worker**: the worker refuses to send the secret to a non-loopback host. The launcher always sets `CONSTELLA_BASE_URL=http://127.0.0.1:<port>` (loopback even when the web binds `0.0.0.0` for vps/portable). A genuine remote worker must opt in with `CONSTELLA_ALLOW_REMOTE_WORKER_BASE_URL=1`, and over plain `http://` it warns that the secret travels in cleartext.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## ποΈ Tables
|
|
127
|
+
|
|
128
|
+
### Process / runtime environment
|
|
129
|
+
|
|
130
|
+
| Env var | Set by | Meaning |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| `CONSTELLA_HOME` | launcher (`--path` / default `~/.constella`) | Runtime root. Relative values are anchored to the launch dir (`INIT_CWD`). |
|
|
133
|
+
| `DATABASE_URL` | launcher | `file:<HOME>/constella.db` (absolute, so app + `drizzle-kit migrate` open the same DB). |
|
|
134
|
+
| `CONSTELLA_PKG_ROOT` | launcher | Installed package root (prebuilt `.next`, `drizzle/`, bundled `skills/`). |
|
|
135
|
+
| `CONSTELLA_RUN_MODE` | launcher | `start \| auth \| vps \| portable`. |
|
|
136
|
+
| `CONSTELLA_PUBLIC` | launcher (`=1`) | A CLI launch is the public runtime β the UI mode-picker is hidden. |
|
|
137
|
+
| `CONSTELLA_VERSION` | launcher | Installed version, for the in-app Update check. |
|
|
138
|
+
| `BETTER_AUTH_SECRET` | `<HOME>/.env` | Session signing key (real, never the public default). |
|
|
139
|
+
| `CONSTELLA_VAULT_KEY` | `<HOME>/.env` | AES-256-GCM key for the `vault` table. |
|
|
140
|
+
| `CONSTELLA_WORKER_SECRET` | `<HOME>/.env` | Shared secret for worker β web auth (`x-worker-secret`). |
|
|
141
|
+
| `CONSTELLA_BASE_URL` | launcher β worker | `http://127.0.0.1:<port>` β loopback target for worker calls. |
|
|
142
|
+
| `CONSTELLA_WORKER_INTERVAL_MS` | optional | Cron tick interval (default `60_000`). |
|
|
143
|
+
| `CONSTELLA_ALLOW_REMOTE_WORKER_BASE_URL` | optional (`=1`) | Allow the worker to call a non-loopback host. |
|
|
144
|
+
| `CONSTELLA_WEB_HEAP_MB` | optional | `--max-old-space-size` for the web child. |
|
|
145
|
+
| `CONSTELLA_DEV` | optional (`=1`) | Permit a `next dev` fallback from a source tree without a build. |
|
|
146
|
+
|
|
147
|
+
### Core tenancy + structural tables (`src/db/schema.ts`)
|
|
148
|
+
|
|
149
|
+
| Table | Key columns | Purpose |
|
|
150
|
+
| --- | --- | --- |
|
|
151
|
+
| `organization` | `id`, `ownerId`, `runMode` (`start\|auth\|vps\|portable`), `archived` | Tenant. `runMode` is the persisted mode. |
|
|
152
|
+
| `member` | `orgId`, `userId`, `role` (`owner\|admin\|member`) | Org membership + roles. |
|
|
153
|
+
| `workspace` | `id`, `orgId`, `slug` (unique), `stack` (JSON), `runMode`, `bootstrap`, `settings` (JSON) | One workspace per org; `settings` holds Telegram/GitHub/source/agents config. |
|
|
154
|
+
| `agent` | `handle`, `role`, `adapter`, `model`, `status`, `health`, `reportsTo`, `dailyCapUsd` | The 10-agent constellation. |
|
|
155
|
+
| `skill` / `agentSkill` | `name`, `native`, `indexed`; join `auto` | Markdown procedures + per-agent enablement. |
|
|
156
|
+
| `goal` / `spec` / `issue` / `task` / `plan` | lifecycle `status`/`col`, `approved`, `auto247` | The work pipeline ([GOALS_SPECS_ISSUES](./GOALS_SPECS_ISSUES.md)). |
|
|
157
|
+
| `message` / `chatSession` / `event` / `decision` | `channel`, `runId`, `seq` | Team Room, DM sessions, live run events, decision log. |
|
|
158
|
+
| `ragChunk` / `kbEntry` / `syncedBlock` / `docIndex` | embeddings + KB layer | Memory nebula ([KB_RAG](./KB_RAG.md), [MEMORY_RAG](./MEMORY_RAG.md)). |
|
|
159
|
+
| `file` | `path`, `gitStatus` (`""\|M\|A\|U\|D`) | Editor mirror + git porcelain status. |
|
|
160
|
+
| `vault` | `ref`, `ciphertext`, `iv` | AES-GCM secrets keyed by provider. |
|
|
161
|
+
| `fileLock` | `workspaceId+path` (PK), `taskId`, `heartbeatAt` | Per-file lock so parallel agents never edit the same file ([SECURITY](./SECURITY.md)). |
|
|
162
|
+
|
|
163
|
+
> The schema defines ~60 tables. The list above covers the ones load-bearing for *architecture*; the work, KB and model tables are documented in their own pages.
|
|
164
|
+
|
|
165
|
+
### Sync engine β indexed prefixes
|
|
166
|
+
|
|
167
|
+
`bin/worker.mjs` only forwards files matching the `INDEXED` regex; `src/server/sync.ts` then routes each path to a per-type indexer:
|
|
168
|
+
|
|
169
|
+
| Path pattern | Indexer | DB target |
|
|
170
|
+
| --- | --- | --- |
|
|
171
|
+
| `.claude/skills/<name>.md` | `indexSkillFile` | `skill` |
|
|
172
|
+
| `.claude/agents/<handle>/(Agent\|skills).md` | `indexAgentFile` | `agent` (+ `agentSkill`) |
|
|
173
|
+
| `Reports/**.md` | `indexReportFile` | `report` |
|
|
174
|
+
| `DOCS/**.md` | `indexDocFile` (kind `docs`) | `docIndex` |
|
|
175
|
+
| `PO/**.md` | `indexDocFile` (kind `po`) | `docIndex` |
|
|
176
|
+
|
|
177
|
+
Any change to a RAG file also schedules a debounced incremental re-embed via `scheduleRagReindex`; a delete drops its chunks via `deindexRagFile`.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## π Mermaid β the sync engine (disk β DB)
|
|
182
|
+
|
|
183
|
+
```mermaid
|
|
184
|
+
sequenceDiagram
|
|
185
|
+
participant FS as Workspace files
|
|
186
|
+
participant W as worker (chokidar)
|
|
187
|
+
participant API as POST /api/sync/file
|
|
188
|
+
participant SYNC as src/server/sync.ts
|
|
189
|
+
participant DB as SQLite
|
|
190
|
+
|
|
191
|
+
FS->>W: add / change / unlink
|
|
192
|
+
Note over W: parse() β {orgId, rel}<br/>INDEXED regex gate<br/>debounce 400ms per key
|
|
193
|
+
W->>API: POST {orgId, rel, event}<br/>x-worker-secret
|
|
194
|
+
API->>API: 401 unless secret matches
|
|
195
|
+
alt event = unlink
|
|
196
|
+
API->>SYNC: deindexFile(orgId, rel)
|
|
197
|
+
SYNC->>DB: delete row + drop RAG chunks
|
|
198
|
+
else add / change
|
|
199
|
+
API->>SYNC: indexFile(orgId, rel)
|
|
200
|
+
SYNC->>SYNC: scheduleRagReindex(orgId, rel)
|
|
201
|
+
SYNC->>DB: upsert (disk wins) + revalidatePath
|
|
202
|
+
end
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## π°οΈ Mermaid β the prompt flow (tick β agent β disk β index)
|
|
208
|
+
|
|
209
|
+
This is the full loop that turns an autonomous tick into real work on disk, then back into the UI.
|
|
210
|
+
|
|
211
|
+
```mermaid
|
|
212
|
+
flowchart LR
|
|
213
|
+
T["worker tick<br/>every 60s"] -->|"POST /api/cron/tick"| API["/api/cron/tick<br/>(401 unless x-worker-secret)"]
|
|
214
|
+
API --> RUN["tickAll({ execute:true, auto:true })"]
|
|
215
|
+
RUN -->|"per active workspace"| TW["tickWorkspace()"]
|
|
216
|
+
TW --> SPAWN["spawn claude / codex<br/>--output-format json<br/>cwd = org workspace"]
|
|
217
|
+
SPAWN -->|"FS jail safe()"| EDIT["agent edits files"]
|
|
218
|
+
EDIT --> DISK[("workspace/ on disk")]
|
|
219
|
+
DISK -->|"chokidar"| WATCH["worker watcher"]
|
|
220
|
+
WATCH -->|"POST /api/sync/file"| SYNC["indexFile()"]
|
|
221
|
+
SYNC --> DB[("SQLite index")]
|
|
222
|
+
DB -->|"revalidatePath"| UI["Next.js UI updates"]
|
|
223
|
+
EDIT -.->|"event rows (runId, seq)"| DB
|
|
224
|
+
|
|
225
|
+
classDef store fill:#1a1a2e,stroke:#e0a44e,color:#fff
|
|
226
|
+
class DISK,DB store
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The agent run itself (model, permission mode, web research, timeouts) is detailed in [AGENTS](./AGENTS.md) and [AI_ARCHITECTURE](./AI_ARCHITECTURE.md). Architecturally, the key point is the **closed loop**: tick β spawn (jailed CLI) β disk β watcher β sync β DB β UI.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## π Step-by-step β trace a single edit end-to-end
|
|
234
|
+
|
|
235
|
+
1. The cron tick (or a DM) advances a workspace; the runner spawns a CLI agent with `cwd` = the org workspace (the FS jail).
|
|
236
|
+
2. The agent writes a file (e.g. `Reports/sprint-3.md`). All writes from server code go through `writeWorkspaceFile` β `safe()`; the CLI itself is confined by `cwd` + the guard/lock hooks.
|
|
237
|
+
3. chokidar (`awaitWriteFinish`, 300 ms stability) fires `add`/`change`.
|
|
238
|
+
4. `parse(abs)` derives `{orgId, rel}` from `<orgId>/workspace/<rel>` and tests the `INDEXED` regex. Non-indexed files are ignored.
|
|
239
|
+
5. A 400 ms per-key debounce coalesces rapid saves, then `POST /api/sync/file` with `x-worker-secret`.
|
|
240
|
+
6. The route authenticates and calls `indexFile(orgId, rel)` β `indexReportFile` β upsert into `report`, plus `scheduleRagReindex`.
|
|
241
|
+
7. `revalidatePath("/reports")` (and `/code`) refresh the UI on next navigation.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## π Examples
|
|
246
|
+
|
|
247
|
+
**Boot from npm (start mode):**
|
|
248
|
+
```bash
|
|
249
|
+
npx constella # default = start mode, 127.0.0.1:3000
|
|
250
|
+
# Constella runtime root : C:\Users\you\.constella
|
|
251
|
+
# Mode : start Β· 127.0.0.1:3000
|
|
252
|
+
# β’ Starting: next start -H 127.0.0.1 -p 3000 + worker
|
|
253
|
+
# watching C:\Users\you\.constella\organizations
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Point the runtime root at a project folder (dev):**
|
|
257
|
+
```bash
|
|
258
|
+
CONSTELLA_HOME=./.constella npx constella --auth --port 4000
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Run web + worker together in development (no global install):**
|
|
262
|
+
```bash
|
|
263
|
+
pnpm dev:all # scripts/dev-all.mjs β next dev + worker (Telegram poll works in dev)
|
|
264
|
+
pnpm start # scripts/start-all.mjs β next start + worker (prod build)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Inspect the index directly:**
|
|
268
|
+
```bash
|
|
269
|
+
sqlite3 ~/.constella/constella.db ".tables"
|
|
270
|
+
sqlite3 ~/.constella/constella.db "SELECT handle,status,health FROM agent;"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## π³οΈ Possible states
|
|
276
|
+
|
|
277
|
+
| Surface | States |
|
|
278
|
+
| --- | --- |
|
|
279
|
+
| Supervised child | running Β· auto-restarting (`n/5 within 60s`) Β· gave up (supervisor exits) |
|
|
280
|
+
| `organization.runMode` | `start` Β· `auth` Β· `vps` Β· `portable` |
|
|
281
|
+
| `workspace.runMode` | `off` Β· `start` Β· `auth` Β· `vps` Β· `portable` (`off` is excluded from `tickAll`) |
|
|
282
|
+
| `workspace.bootstrap` | `pending` Β· `template-only` Β· `enriching` Β· `done` |
|
|
283
|
+
| `agent.status` | `idle` Β· `working` Β· `review` Β· `blocked` |
|
|
284
|
+
| `agent.health` | `alive` Β· `stale` Β· `down` |
|
|
285
|
+
| `file.gitStatus` | `""` Β· `M` Β· `A` Β· `U` Β· `D` |
|
|
286
|
+
| Worker base URL guard | loopback (allowed) Β· non-loopback + `ALLOW_REMOTE` Β· refused (exit 1) |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## π°οΈ Related integrations
|
|
291
|
+
|
|
292
|
+
- **Worker endpoints**: `/api/cron/tick`, `/api/sync/file`, `/api/telegram/poll` β all behind `x-worker-secret`.
|
|
293
|
+
- **Telegram** long-poll runs inside the worker β [TELEGRAM](./TELEGRAM.md).
|
|
294
|
+
- **GitHub** git status flows into `file.gitStatus` β [GITHUB](./GITHUB.md).
|
|
295
|
+
- **RAG/KB** re-embedding is triggered by the sync engine β [KB_RAG](./KB_RAG.md), [MEMORY_RAG](./MEMORY_RAG.md).
|
|
296
|
+
- **Public API / MCP** are separate inbound surfaces (not worker-secret) β [PUBLIC_API](./PUBLIC_API.md), [MCP](./MCP.md).
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## π³οΈ Security
|
|
301
|
+
|
|
302
|
+
- **FS jail** `safe()` β lexical + symlink checks; the workspace root is never deletable through it. Org id is validated before any path is built.
|
|
303
|
+
- **Worker secret fails closed** β `/api/cron/tick` and `/api/sync/file` reject every request when no secret is configured (an unset secret is *not* an open door).
|
|
304
|
+
- **SSRF guard** β the worker only sends its secret to loopback unless explicitly overridden; cleartext remote use is warned.
|
|
305
|
+
- **Vault** β secrets live only in the `vault` table (AES-256-GCM via `CONSTELLA_VAULT_KEY`), never on provider rows; `.env` is written `0o600`.
|
|
306
|
+
- **Single writer** β the worker has no DB handle; all writes go through the web process, so there is one authority for consistency.
|
|
307
|
+
- Full detail in [SECURITY](./SECURITY.md).
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## π Troubleshooting
|
|
312
|
+
|
|
313
|
+
| Symptom | Likely cause | Where to look |
|
|
314
|
+
| --- | --- | --- |
|
|
315
|
+
| File edited but UI stale | watcher not running, or path not in `INDEXED` | worker logs (`watching β¦`); `bin/worker.mjs` `INDEXED` regex |
|
|
316
|
+
| `401 unauthorized` on tick/sync | `CONSTELLA_WORKER_SECRET` mismatch between web + worker | `<HOME>/.env`; both children inherit it from the launcher |
|
|
317
|
+
| Worker exits at start | `CONSTELLA_BASE_URL` is non-loopback without override | set loopback or `CONSTELLA_ALLOW_REMOTE_WORKER_BASE_URL=1` |
|
|
318
|
+
| Two separate databases appear | standalone server chdir without `INIT_CWD` | use `pnpm start` / the CLI (they set `INIT_CWD`); see `src/lib/runtime-root.ts` warning |
|
|
319
|
+
| Fresh DB has no tables | `drizzle-kit migrate` failed on first boot | reinstall the package; check `drizzle/` ships; boot aborts on a fresh-DB migrate failure by design |
|
|
320
|
+
| Crash-loop "giving up" | a child crashed 5Γ in 60s | check the OOM hint; raise `CONSTELLA_WEB_HEAP_MB` if it's a JS-heap OOM |
|
|
321
|
+
|
|
322
|
+
More in [TROUBLESHOOTING](./TROUBLESHOOTING.md) and [FAQ](./FAQ.md).
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## β¦ Related links
|
|
327
|
+
|
|
328
|
+
- [AI_ARCHITECTURE](./AI_ARCHITECTURE.md) β the cognitive layer (agents, RAG, context).
|
|
329
|
+
- [AGENTS](./AGENTS.md) β the 10-agent constellation and how runs are spawned.
|
|
330
|
+
- [CONFIGURATION](./CONFIGURATION.md) β env vars and settings in depth.
|
|
331
|
+
- [INSTALLATION](./INSTALLATION.md) Β· [START_MODE](./START_MODE.md) Β· [AUTH_MODE](./AUTH_MODE.md) Β· [VPS_MODE](./VPS_MODE.md) Β· [PORTABLE_MODE](./PORTABLE_MODE.md)
|
|
332
|
+
- [KB_RAG](./KB_RAG.md) Β· [MEMORY_RAG](./MEMORY_RAG.md) Β· [SYNCED_BLOCKS](./SYNCED_BLOCKS.md)
|
|
333
|
+
- [SECURITY](./SECURITY.md) Β· [TROUBLESHOOTING](./TROUBLESHOOTING.md) Β· [FAQ](./FAQ.md)
|
|
334
|
+
- [TELEGRAM](./TELEGRAM.md) Β· [GITHUB](./GITHUB.md) Β· [PUBLIC_API](./PUBLIC_API.md) Β· [MCP](./MCP.md)
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
[β Docs index](./README.md) Β· [π§π· PortuguΓͺs](../pt/AUTH_MODE.md) Β· [β¦ Constella](../../README.md)
|
|
2
|
+
|
|
3
|
+
# Auth Mode π°οΈ
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
> Real email + password gating in front of the central ship β for when more than one human shares the same machine, but you still want a private, loopback-only control plane.
|
|
8
|
+
|
|
9
|
+
Auth mode is the run mode where every session must pass a credential gate. Unlike `start` mode (which auto-creates and auto-signs-in a local operator), `auth` mode shows the real login screen, signs sessions with a mandatory `BETTER_AUTH_SECRET`, and supports TOTP 2FA and WebAuthn passkeys. It still binds to `127.0.0.1`, so the surface is the same local-only orbit as `start` β only the front door is locked.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## β¦ When to use
|
|
14
|
+
|
|
15
|
+
Use `auth` mode when:
|
|
16
|
+
|
|
17
|
+
- A **shared workstation** hosts Constella and you do not want anyone with physical access to land straight in the app.
|
|
18
|
+
- You want a **real account** (email + password, optional 2FA / passkey) instead of the auto-provisioned `operator@constella.dev` account.
|
|
19
|
+
- You want session signing with a **persisted secret**, but you still want to keep the listener on loopback (no network exposure).
|
|
20
|
+
|
|
21
|
+
Reach for a different mode when:
|
|
22
|
+
|
|
23
|
+
| You want⦠| Use |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Zero-friction local, single user, no login | [START_MODE](./START_MODE.md) |
|
|
26
|
+
| Remote access over a private tailnet, in Docker | [VPS_MODE](./VPS_MODE.md) |
|
|
27
|
+
| The whole runtime carried on a USB drive | [PORTABLE_MODE](./PORTABLE_MODE.md) |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## π How it works
|
|
32
|
+
|
|
33
|
+
`auth` is one of four `RunMode` values defined in `src/lib/run-mode.ts`:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
export type RunMode = "start" | "auth" | "vps" | "portable";
|
|
37
|
+
|
|
38
|
+
export const RUN_MODES: Record<RunMode, { label: string; requiresLogin: boolean; note: string }> = {
|
|
39
|
+
start: { label: "Start", requiresLogin: false, note: "Local auto-created account Β· always signed in." },
|
|
40
|
+
auth: { label: "Auth", requiresLogin: true, note: "Email + password required each session." },
|
|
41
|
+
vps: { label: "VPS", requiresLogin: true, note: "Access over your Tailscale tailnet; runs in Docker." },
|
|
42
|
+
portable: { label: "Portable", requiresLogin: true, note: "USB drive mounted as root across machines." },
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The mode is selected by the launch flag in `bin/constella.mjs` and exported into the environment as `CONSTELLA_RUN_MODE`. The server reads it back with `getRunMode()`; `requiresLogin()` returns `true` for `auth`.
|
|
47
|
+
|
|
48
|
+
Three pillars define the mode:
|
|
49
|
+
|
|
50
|
+
1. **`requiresLogin: true`** β `requireWorkspace()` (in `src/lib/workspace.ts`) sends an unauthenticated request to `/login`, not to `/api/dev-login`. There is no auto sign-in.
|
|
51
|
+
2. **Mandatory `BETTER_AUTH_SECRET`** β every network-capable mode (`auth`, `vps`, `portable`) must boot with a real signing secret or it refuses to serve (see [Security](#-security)).
|
|
52
|
+
3. **`127.0.0.1` bind** β `auth` keeps the same loopback host as `start`; only `vps` and `portable` bind `0.0.0.0`.
|
|
53
|
+
|
|
54
|
+
### The login surface (`better-auth`)
|
|
55
|
+
|
|
56
|
+
`src/lib/auth.ts` configures `better-auth` with:
|
|
57
|
+
|
|
58
|
+
- **Email + password** always enabled (`emailAndPassword: { enabled: true, autoSignIn: true, requireEmailVerification: false }`).
|
|
59
|
+
- **TOTP 2FA** via the `twoFactor()` plugin (Profile β Security).
|
|
60
|
+
- **WebAuthn passkeys** via custom `/api/passkey/*` routes built on `@simplewebauthn` (the login form offers a passkey button).
|
|
61
|
+
- **Social providers** (GitHub / Google) only when their env credentials are present β used for account linking, not as the primary auth path.
|
|
62
|
+
- **30-day sessions** (`expiresIn: 60 * 60 * 24 * 30`).
|
|
63
|
+
- **Secure cookies** whenever the base URL is `https://` (`useSecureCookies: BASE_URL.startsWith("https://")`). In plain `auth` over local http, cookies stay relaxed; behind an https reverse proxy they become `Secure`.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## π Main flow
|
|
68
|
+
|
|
69
|
+
```mermaid
|
|
70
|
+
flowchart TD
|
|
71
|
+
A["constella --auth"] --> B["bin/constella.mjs<br/>CONSTELLA_RUN_MODE=auth<br/>host = 127.0.0.1"]
|
|
72
|
+
B --> C["ensureSecret() persists<br/>BETTER_AUTH_SECRET to ~/.constella/.env"]
|
|
73
|
+
C --> D["boot.ts β assertAuthSecret()"]
|
|
74
|
+
D -->|secret present| E["server serves"]
|
|
75
|
+
D -->|secret missing| X["process.exit(1)"]
|
|
76
|
+
E --> F["browser hits any (app) page"]
|
|
77
|
+
F --> G["requireWorkspace()"]
|
|
78
|
+
G -->|no session| H["redirect /login"]
|
|
79
|
+
H --> I["LoginForm: email + password"]
|
|
80
|
+
I -->|2FA enabled| J["TOTP code β verifyTotp"]
|
|
81
|
+
I -->|passkey| K["/api/passkey/authenticate"]
|
|
82
|
+
J --> L["session cookie set Β· redirect /"]
|
|
83
|
+
K --> L
|
|
84
|
+
I -->|password ok, no 2FA| L
|
|
85
|
+
G -->|session ok| M["scoped workspace returned"]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## πͺ Key concepts
|
|
91
|
+
|
|
92
|
+
| Concept | Where | Meaning |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| `RunMode` | `src/lib/run-mode.ts` | `"auth"` is one of four modes; drives login + bind behaviour. |
|
|
95
|
+
| `requiresLogin()` | `src/lib/run-mode.ts` | Returns `true` for `auth` β the app demands a credential. |
|
|
96
|
+
| `assertAuthSecret()` | `src/lib/auth.ts` | Hard boot gate: refuses to run a network mode without `BETTER_AUTH_SECRET`. |
|
|
97
|
+
| `requireWorkspace()` | `src/lib/workspace.ts` | Per-page guard; redirects unauthenticated `auth`-mode requests to `/login`. |
|
|
98
|
+
| `LoginForm` | `src/app/(auth)/login/login-form.tsx` | Email/password + 2FA + passkey UI. |
|
|
99
|
+
| `auth` (better-auth) | `src/lib/auth.ts` | The configured auth server (email/pw, 2FA, social, sessions). |
|
|
100
|
+
| `createSessionCookie()` | `src/server/passkey-login.ts` | Mints a real better-auth session after a passkey assertion. |
|
|
101
|
+
| `member.role` | `src/db/schema.ts` | `owner` \| `admin` \| `member` β org membership roles. |
|
|
102
|
+
|
|
103
|
+
### `auth` vs `start` β the contrast
|
|
104
|
+
|
|
105
|
+
`start` and `auth` share the same loopback host and the same dual-process runtime; they differ entirely at the **front door**.
|
|
106
|
+
|
|
107
|
+
| Dimension | `start` | `auth` |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `requiresLogin` | `false` | `true` |
|
|
110
|
+
| Login screen | skipped | shown (`/login`) |
|
|
111
|
+
| Account | auto-provisioned `operator@constella.dev` / `operator123` | a real account you create/sign into |
|
|
112
|
+
| Auto sign-in | yes β `/api/dev-login` | no |
|
|
113
|
+
| `BETTER_AUTH_SECRET` | persisted but not strictly required by `assertAuthSecret()` | **mandatory** (boot refuses without it) |
|
|
114
|
+
| Bind host | `127.0.0.1` | `127.0.0.1` |
|
|
115
|
+
| 2FA / passkeys | available but pointless (auto-login) | the point of the mode |
|
|
116
|
+
| Shared machine safe? | no (anyone with the box is in) | yes (credential gate) |
|
|
117
|
+
| `ensureLocalOperator()` | called | throws β "start-mode only" |
|
|
118
|
+
|
|
119
|
+
The predictable `operator/operator123` credential is provisioned **only** in `start` mode. `ensureLocalOperator()` (in `src/server/dev-auth.ts`) explicitly throws if `getRunMode() !== "start"`, so a network mode can never carry a default remote login.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## π Step-by-step
|
|
124
|
+
|
|
125
|
+
### 1. Launch in auth mode
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx constella --auth
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`bin/constella.mjs` sets `CONSTELLA_RUN_MODE=auth`, picks `host = 127.0.0.1` (only `vps`/`portable` use `0.0.0.0`), and `port` defaults to `3000` (override with `--port`).
|
|
132
|
+
|
|
133
|
+
### 2. Secrets are persisted
|
|
134
|
+
|
|
135
|
+
On every launch, `bin/constella.mjs` ensures three secrets exist under the runtime root and writes them (mode `0o600`) to `~/.constella/.env`:
|
|
136
|
+
|
|
137
|
+
| Secret | Purpose |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `BETTER_AUTH_SECRET` | Signs session cookies (mandatory in `auth`). |
|
|
140
|
+
| `CONSTELLA_VAULT_KEY` | AES-256-GCM key for the provider-secret vault. |
|
|
141
|
+
| `CONSTELLA_WORKER_SECRET` | Shared secret the worker presents to the web (`x-worker-secret`). |
|
|
142
|
+
|
|
143
|
+
`ensureSecret()` reuses an existing persisted value, prefers an env override, and otherwise generates one once. Persisting (not regenerating) means your login sessions and the encrypted vault survive a restart.
|
|
144
|
+
|
|
145
|
+
### 3. Boot gate fires
|
|
146
|
+
|
|
147
|
+
At first request, `reconcileOnBoot()` (in `src/server/boot.ts`) calls `assertAuthSecret()` **before anything else**. In `auth` without a real secret, the process logs `[boot] FATAL:` and calls `process.exit(1)` β the server never serves a forgeable cookie.
|
|
148
|
+
|
|
149
|
+
### 4. Sign in
|
|
150
|
+
|
|
151
|
+
The browser hits any `(app)` page β `requireWorkspace()` finds no session β redirects to `/login`. The `LoginForm`:
|
|
152
|
+
|
|
153
|
+
- Pre-fills `operator@constella.dev` but accepts any email.
|
|
154
|
+
- Calls `signIn.email({ email, password })`. If the email is unknown it falls back to `signUp.email(...)` (create-on-first-login).
|
|
155
|
+
- The submit button is disabled until the password is at least 8 characters.
|
|
156
|
+
|
|
157
|
+
### 5. Optional second factor
|
|
158
|
+
|
|
159
|
+
- **TOTP 2FA:** if enabled, `signIn.email` returns `twoFactorRedirect`; the form switches to a 6-digit code field and calls `authClient.twoFactor.verifyTotp({ code })`.
|
|
160
|
+
- **Passkey:** the "passkey" button posts to `/api/passkey/authenticate/options`, runs `startAuthentication(...)` in the browser, then posts the assertion to `/api/passkey/authenticate/verify`. On success the server mints a real session cookie via `createSessionCookie()`.
|
|
161
|
+
|
|
162
|
+
### 6. Manage second factors (Profile β Security)
|
|
163
|
+
|
|
164
|
+
- **Enable 2FA:** `authClient.twoFactor.enable({ password })` β scan the TOTP URI β `verifyTotp({ code })`. Disable with `authClient.twoFactor.disable({ password })`.
|
|
165
|
+
- **Passkeys:** registered via the `/api/passkey/register/*` routes; managed (rename / remove) by `removePasskey` / rename actions in `src/server/actions/profile-actions.ts`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## π³οΈ Examples
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Standard auth-mode launch on the default port
|
|
173
|
+
npx constella --auth
|
|
174
|
+
|
|
175
|
+
# Auth mode on a custom port
|
|
176
|
+
npx constella --auth --port 4000
|
|
177
|
+
|
|
178
|
+
# Auth mode with the runtime root somewhere else
|
|
179
|
+
npx constella --auth --path /srv/constella-home
|
|
180
|
+
|
|
181
|
+
# Force the first-run onboarding wizard, still under the auth gate
|
|
182
|
+
npx constella --auth --onboarding
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
> The run-mode **picker** on the login screen appears only in developer mode (`isDevMode()` in `src/lib/build-mode.ts`). A public CLI launch sets `CONSTELLA_PUBLIC=1`, so the mode is fixed by the launch flag and the picker is hidden.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## β¦ Possible states
|
|
190
|
+
|
|
191
|
+
| State | Cause | Symptom |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| **Login required** | `auth` mode, no session | Browser redirected to `/login`. |
|
|
194
|
+
| **Password rejected** | Wrong password for an existing account | `login.failed` message; no fallthrough to signup (email exists). |
|
|
195
|
+
| **New account created** | Unknown email + valid password | `signUp.email` succeeds, redirect to `/`. |
|
|
196
|
+
| **2FA challenge** | Account has TOTP enabled | Code field shown; needs a 6-digit TOTP. |
|
|
197
|
+
| **Passkey login** | User clicks the passkey button | Browser WebAuthn prompt; session minted server-side. |
|
|
198
|
+
| **Boot refused** | Network mode, missing `BETTER_AUTH_SECRET` | `[boot] FATAL` + `process.exit(1)`; server never starts. |
|
|
199
|
+
| **Auto-login attempted** | `ensureLocalOperator` reached in `auth` | Throws `"ensureLocalOperator is start-mode only"` (defense-in-depth). |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## π°οΈ Related integrations
|
|
204
|
+
|
|
205
|
+
- **Org isolation** β after sign-in, `requireWorkspace()` resolves the active org through a `member` join so a session can never point at another tenant's org (`getActiveOrg` in `src/lib/workspace.ts`). Roles are `owner` / `admin` / `member`.
|
|
206
|
+
- **Vault** β provider secrets are encrypted with `CONSTELLA_VAULT_KEY`, persisted alongside `BETTER_AUTH_SECRET` in `~/.constella/.env`. See [SECURITY](./SECURITY.md).
|
|
207
|
+
- **Worker** β the 24/7 worker authenticates to the web with `x-worker-secret` (`CONSTELLA_WORKER_SECRET`) over loopback, independent of the human login. See [ARCHITECTURE](./ARCHITECTURE.md).
|
|
208
|
+
- **Public API / PAT** β programmatic access uses `Bearer cn_<token>` PATs, a separate path from the browser session. See [PUBLIC_API](./PUBLIC_API.md).
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## π³οΈ Security
|
|
213
|
+
|
|
214
|
+
- **Mandatory signing secret.** `auth` (like `vps`/`portable`) **must** boot with a real `BETTER_AUTH_SECRET`. Without one, sessions would be signed with better-auth's public default key (forgeable cookies), because better-auth only throws on the default under `NODE_ENV=production`. `assertAuthSecret()` closes that gap by exiting the process. `start` is exempt because it is local-only with auto-login.
|
|
215
|
+
- **Loopback bind.** `auth` binds `127.0.0.1`; the listener is not reachable from the network. If you place an https reverse proxy in front, set `BETTER_AUTH_URL` to the public `https://` origin so session cookies are marked `Secure`.
|
|
216
|
+
- **No default remote credential.** The `operator/operator123` account is start-mode-only and never provisioned in `auth`.
|
|
217
|
+
- **Real 2FA / passkeys.** TOTP secrets live in the `two_factor` table; WebAuthn credentials in the `passkey` table (COSE public key, counter, transports). Passkey challenges are stored in short-lived (`maxAge: 300`) httpOnly cookies between the options and verify round-trips (`src/lib/passkey.ts`).
|
|
218
|
+
- **30-day sessions.** Sessions expire after 30 days; the `account` deletion path cascades to sessions, accounts, passkeys and tokens.
|
|
219
|
+
- **Cross-tenant safety.** `activeOrgId` is treated as attacker-controllable and always re-validated through a membership join.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## π Troubleshooting
|
|
224
|
+
|
|
225
|
+
| Symptom | Likely cause | Fix |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| Server exits immediately with `[boot] FATAL: BETTER_AUTH_SECRET is required` | Network mode booted without a secret | Let the CLI persist one (default), or set `BETTER_AUTH_SECRET` in the environment / `~/.constella/.env`. |
|
|
228
|
+
| Login screen never appears (auto-signed-in) | You actually launched `start`, not `auth` | Check the boot line `Mode : auth Β· 127.0.0.1:3000`; relaunch with `--auth`. |
|
|
229
|
+
| "ensureLocalOperator is start-mode only" in logs | Auto-login code path reached under `auth` | Expected guard β there is no auto-login in `auth`; sign in manually. |
|
|
230
|
+
| Passkey button fails | `BETTER_AUTH_URL` host mismatch (RP id) | Set `BETTER_AUTH_URL` to the exact origin you browse from; `rpID()` is its hostname. |
|
|
231
|
+
| Cookies not `Secure` behind https | `BASE_URL` still `http://localhost:3000` | Set `BETTER_AUTH_URL` to the `https://` origin so `useSecureCookies` flips on. |
|
|
232
|
+
| Forgot the operator password (startβauth migration) | Default credential only exists in `start` | In `auth`, create/sign into a real account; do not rely on `operator123`. |
|
|
233
|
+
| Can't reach the app from another machine | `auth` binds loopback by design | Use [VPS_MODE](./VPS_MODE.md) for remote access. |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## β¦ Related links
|
|
238
|
+
|
|
239
|
+
- [START_MODE](./START_MODE.md) β the auto-login local mode `auth` contrasts with.
|
|
240
|
+
- [VPS_MODE](./VPS_MODE.md) β network-exposed mode over a tailnet, in Docker.
|
|
241
|
+
- [PORTABLE_MODE](./PORTABLE_MODE.md) β the USB-drive run mode.
|
|
242
|
+
- [CONFIGURATION](./CONFIGURATION.md) β env vars, secrets, and the runtime root.
|
|
243
|
+
- [INSTALLATION](./INSTALLATION.md) β installing and first launch.
|
|
244
|
+
- [SECURITY](./SECURITY.md) β vault, scrubbing, FS jail, session model.
|
|
245
|
+
- [ARCHITECTURE](./ARCHITECTURE.md) β dual-process web + worker, boot reconcile.
|
|
246
|
+
- [PUBLIC_API](./PUBLIC_API.md) β PAT-based programmatic access.
|
|
247
|
+
- [TROUBLESHOOTING](./TROUBLESHOOTING.md) β broader failure catalogue.
|