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
|
+
[← Índice](./README.md) · [🇬🇧 English](../en/ARCHITECTURE.md) · [✦ Constella](../../README.pt-BR.md)
|
|
2
|
+
|
|
3
|
+
# 🌌 Arquitetura — a nave central
|
|
4
|
+
|
|
5
|
+
A Constella é um plano de controle local-first: um único processo Node supervisiona um **servidor web** e um **worker 24/7**, ambos orbitando uma raiz de runtime em disco onde cada organização mantém um workspace isolado. O diretório é a fonte da verdade; o SQLite é o índice que mantém a UI e a busca em acordo.
|
|
6
|
+
|
|
7
|
+
> ✦ Este documento mapeia a camada *estrutural*: topologia de processos, raiz de runtime + isolamento de organização, a jaula de filesystem, o armazenamento SQLite/Drizzle, o motor de sincronização + watcher de arquivos, e o cron tick que conduz o trabalho autônomo. Para a camada *cognitiva* (como os agentes pensam, RAG, KB) veja [AI_ARCHITECTURE](./AI_ARCHITECTURE.md).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🛰️ Quando usar este doc
|
|
12
|
+
|
|
13
|
+
- Você precisa entender **como a Constella inicializa** e qual processo faz o quê.
|
|
14
|
+
- Está depurando **por que uma edição de arquivo não apareceu** na UI (motor de sincronização).
|
|
15
|
+
- Está raciocinando sobre **isolamento multi-tenant** (uma raiz de runtime, várias organizações).
|
|
16
|
+
- Está reforçando ou auditando a fronteira de confiança **worker ↔ web**.
|
|
17
|
+
- Quer o **mapa em nível de tabela** do banco de dados (`src/db/schema.ts`).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🚀 Como funciona (visão geral)
|
|
22
|
+
|
|
23
|
+
Um único launcher — `bin/constella.mjs` — resolve o modo de execução, prepara a raiz de runtime e os segredos, aplica as migrações do banco e então **supervisiona dois filhos de longa duração**:
|
|
24
|
+
|
|
25
|
+
| Filho | Entrada | Papel |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| **web** | `next start -H <host> -p <port>` (a partir de `PKG_ROOT`) | A app Next.js 16: UI, server actions, todas as rotas `/api`, orquestração de agentes. |
|
|
28
|
+
| **worker** | `bin/worker.mjs` | Condutor headless 24/7: cron tick, o watcher de arquivos chokidar, o long-poll do Telegram. Fala com a web por HTTP em loopback. |
|
|
29
|
+
|
|
30
|
+
O worker nunca toca no banco diretamente. Ele apenas faz chamadas HTTP autenticadas de volta para o servidor web (`x-worker-secret`), de modo que todas as escritas passam por um único processo e um único conjunto de server actions. Isso mantém a fronteira de confiança pequena e o banco com um único escritor.
|
|
31
|
+
|
|
32
|
+
```mermaid
|
|
33
|
+
flowchart TB
|
|
34
|
+
subgraph Launcher["bin/constella.mjs (supervisor)"]
|
|
35
|
+
SUP["supervise(): reinicia em crash<br/>máx 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[("Raiz de runtime<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["CLIs de agente<br/>cwd = workspace da org (jaula FS)"]
|
|
49
|
+
CLI -->|edita arquivos| DISK
|
|
50
|
+
|
|
51
|
+
classDef store fill:#1a1a2e,stroke:#e0a44e,color:#fff
|
|
52
|
+
class DB,DISK store
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🌠 Fluxo principal — do boot ao regime estável
|
|
58
|
+
|
|
59
|
+
A sequência de boot do launcher (`bin/constella.mjs`), em ordem:
|
|
60
|
+
|
|
61
|
+
1. **Resolver o modo de execução** — a flag explícita (`--start|--auth|--vps|--portable`) vence, depois o legado `--bind`, padrão `start`. Veja [START_MODE](./START_MODE.md), [AUTH_MODE](./AUTH_MODE.md), [VPS_MODE](./VPS_MODE.md), [PORTABLE_MODE](./PORTABLE_MODE.md).
|
|
62
|
+
2. **Resolver a raiz de runtime** — `CONSTELLA_HOME` / `--path` vence; caso contrário `~/.constella`. O modo portátil sem path enumera drives USB removíveis e pergunta. `mkdir -p <HOME>/organizations`.
|
|
63
|
+
3. **Fixar caminhos** — `DATABASE_URL=file:<HOME>/constella.db`, `CONSTELLA_PKG_ROOT=<dir de instalação>`. `PKG_ROOT` é onde vivem o `.next` pré-compilado, as migrações `drizzle/` e os configs (não o diretório de lançamento).
|
|
64
|
+
4. **Persistir segredos** — ler/gerar `BETTER_AUTH_SECRET`, `CONSTELLA_VAULT_KEY`, `CONSTELLA_WORKER_SECRET` e gravá-los em `<HOME>/.env` com modo `0o600`. Gerados uma vez; reutilizados entre reinícios para que as sessões + o vault criptografado sobrevivam.
|
|
65
|
+
5. **Verificação de disco no portátil** — recusa `< 32 GB` livres (fatal); `≥ 32 GB` está ok.
|
|
66
|
+
6. **Aplicar migrações** — `drizzle-kit migrate --config drizzle.config.mjs` a partir de `PKG_ROOT`. Idempotente. Um banco *novo* que falha ao migrar aborta o boot (sem tabelas → toda requisição dá 500).
|
|
67
|
+
7. **Build no primeiro run (apenas fallback)** — o pacote publicado já traz um `.next` pré-compilado, então isso é pulado. A partir de uma árvore de código-fonte sem build, ele roda `next build`; recusa cair silenciosamente para `next dev` em um run público a menos que `CONSTELLA_DEV=1`.
|
|
68
|
+
8. **Supervisionar web + worker** — sobe o servidor web e, ~1,5 s depois, o worker (para o Next ganhar vantagem). Cada filho é envolto em `supervise()`; em uma saída inesperada ele auto-reinicia (limitado: `MAX_RESTARTS = 5` dentro de `WINDOW_MS = 60_000`), senão o supervisor desiste e sai.
|
|
69
|
+
|
|
70
|
+
Já em regime, o **worker** espera o servidor responder (`waitForServer`, até ~90 s) e então:
|
|
71
|
+
|
|
72
|
+
- Dispara o **cron tick** imediatamente e a cada `INTERVAL` (`CONSTELLA_WORKER_INTERVAL_MS`, padrão `60_000` ms).
|
|
73
|
+
- Inicia o **watcher chokidar** sobre `<HOME>/organizations`.
|
|
74
|
+
- Roda o loop de **long-poll do Telegram** (`getUpdates` aguarda ~25 s no lado do servidor; intervalo de ~1 s entre polls).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🪐 Conceitos-chave
|
|
79
|
+
|
|
80
|
+
### Raiz de runtime + isolamento por organização
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
~/.constella/ ← raiz de runtime (CONSTELLA_HOME ou --path)
|
|
84
|
+
├─ .env ← segredos persistidos (modo 0600)
|
|
85
|
+
├─ constella.db ← SQLite (WAL) — o índice
|
|
86
|
+
├─ cache/ ← cache do models.dev, etc.
|
|
87
|
+
├─ backups/ ← backups de .env + db no update
|
|
88
|
+
└─ organizations/
|
|
89
|
+
└─ <orgId>/
|
|
90
|
+
└─ workspace/ ← a árvore isolada e sandboxed da org
|
|
91
|
+
├─ .claude/ ← agents/, skills/, BRIEF.md (config DENTRO do workspace)
|
|
92
|
+
├─ DOCS/ PO/ Reports/
|
|
93
|
+
├─ specs/ issues/ mock/
|
|
94
|
+
├─ uploads/ ← anexos do operador, mídia do Telegram
|
|
95
|
+
└─ <o produto que os agentes constroem>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
O diretório de workspace é indexado pelo **`organization.id` estável** (nunca pelo slug renomeável). Uma migração única de boot renomeia um diretório legado `constella/` para `workspace/` para que as organizações existentes mantenham seus dados (caindo para uma cópia em uma movimentação entre dispositivos, nunca apagando o diretório legado).
|
|
99
|
+
|
|
100
|
+
### A jaula de filesystem — `safe()`
|
|
101
|
+
|
|
102
|
+
Toda leitura/escrita de workspace passa por `safe(root, rel)` em `src/lib/fs-workspace.ts`. É o único ponto de estrangulamento que mantém um agente sob prompt-injection (ou um caminho com bug) dentro da sua própria org:
|
|
103
|
+
|
|
104
|
+
1. **Verificação léxica** — `normalize(join(root, rel))` deve ser igual a `root` ou começar com `root + sep`. Como `join` re-enraiza caminhos absolutos, com letra de drive e UNC sob `root`, isso bloqueia `../`, escapes absolutos e truques de drive do Windows.
|
|
105
|
+
2. **Verificação de symlink** — resolve o caminho real do ancestral existente mais próximo (`realAncestor`) e re-verifica que ele ainda está sob o `root` real. Isso derrota um symlink *plantado dentro* do workspace que de outra forma tunelaria para outra org ou para o filesystem mais amplo.
|
|
106
|
+
|
|
107
|
+
`orgRoot()` adicionalmente valida o id da org (`/^[A-Za-z0-9_-]{6,64}$/`) antes mesmo de tocar em um caminho, então um id malformado não consegue atravessar. Diretórios pesados de build/dependência (`node_modules`, `.git`, `.next`, `dist`, `.testdev`, …) são pulados por `listFiles()` via `HEAVY_DIRS`.
|
|
108
|
+
|
|
109
|
+
### O diretório é a verdade, o banco é o índice
|
|
110
|
+
|
|
111
|
+
O filesystem é canônico; o banco **espelha** ele. Os indexadores em `src/server/sync.ts` são upserts idempotentes e **o disco sempre vence no conflito**. O mesmo arquivo escrito por um agente e depois re-indexado pelo watcher atualiza *uma* linha (indexada pelo título H1 ou pelo caminho relativo), nunca duplica.
|
|
112
|
+
|
|
113
|
+
### SQLite + Drizzle
|
|
114
|
+
|
|
115
|
+
`src/db/index.ts` abre o `better-sqlite3` contra o `DATABASE_URL` resolvido, define `journal_mode = WAL` e `foreign_keys = ON`, e o envolve com `drizzle-orm`. Também exporta o handle bruto `sqlite` para **DDL de boot sem migração** (`CREATE TABLE IF NOT EXISTS` + `ALTER ADD COLUMN` protegido) — usado para adicionar tabelas/colunas a bancos existentes *sem* `drizzle-kit push`, que faria o histórico de migrações deste projeto derivar. Veja [SECURITY](./SECURITY.md) e [TROUBLESHOOTING](./TROUBLESHOOTING.md) para a ressalva do `db:push`.
|
|
116
|
+
|
|
117
|
+
### Fronteira de confiança worker ↔ web
|
|
118
|
+
|
|
119
|
+
O worker detém o privilegiado `CONSTELLA_WORKER_SECRET` e o anexa como `x-worker-secret` em toda chamada. Duas proteções importam:
|
|
120
|
+
|
|
121
|
+
- **Fail closed no servidor**: `/api/cron/tick` e `/api/sync/file` retornam `401` a menos que o header seja igual ao segredo configurado. Um segredo não definido **não** os deixa abertos — eles rejeitam todo mundo.
|
|
122
|
+
- **Guarda SSRF / exfiltração no worker**: o worker se recusa a enviar o segredo para um host não-loopback. O launcher sempre define `CONSTELLA_BASE_URL=http://127.0.0.1:<port>` (loopback mesmo quando a web faz bind em `0.0.0.0` para vps/portable). Um worker remoto genuíno precisa optar explicitamente com `CONSTELLA_ALLOW_REMOTE_WORKER_BASE_URL=1`, e sobre `http://` puro ele avisa que o segredo viaja em texto-claro.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 🗃️ Tabelas
|
|
127
|
+
|
|
128
|
+
### Ambiente de processo / runtime
|
|
129
|
+
|
|
130
|
+
| Variável de ambiente | Definida por | Significado |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| `CONSTELLA_HOME` | launcher (`--path` / padrão `~/.constella`) | Raiz de runtime. Valores relativos são ancorados ao diretório de lançamento (`INIT_CWD`). |
|
|
133
|
+
| `DATABASE_URL` | launcher | `file:<HOME>/constella.db` (absoluto, para que app + `drizzle-kit migrate` abram o mesmo banco). |
|
|
134
|
+
| `CONSTELLA_PKG_ROOT` | launcher | Raiz do pacote instalado (`.next` pré-compilado, `drizzle/`, `skills/` empacotado). |
|
|
135
|
+
| `CONSTELLA_RUN_MODE` | launcher | `start \| auth \| vps \| portable`. |
|
|
136
|
+
| `CONSTELLA_PUBLIC` | launcher (`=1`) | Um lançamento por CLI é o runtime público → o seletor de modo da UI fica oculto. |
|
|
137
|
+
| `CONSTELLA_VERSION` | launcher | Versão instalada, para a verificação de Update na app. |
|
|
138
|
+
| `BETTER_AUTH_SECRET` | `<HOME>/.env` | Chave de assinatura de sessão (real, nunca o padrão público). |
|
|
139
|
+
| `CONSTELLA_VAULT_KEY` | `<HOME>/.env` | Chave AES-256-GCM para a tabela `vault`. |
|
|
140
|
+
| `CONSTELLA_WORKER_SECRET` | `<HOME>/.env` | Segredo compartilhado para a auth worker → web (`x-worker-secret`). |
|
|
141
|
+
| `CONSTELLA_BASE_URL` | launcher → worker | `http://127.0.0.1:<port>` — alvo loopback para chamadas do worker. |
|
|
142
|
+
| `CONSTELLA_WORKER_INTERVAL_MS` | opcional | Intervalo do cron tick (padrão `60_000`). |
|
|
143
|
+
| `CONSTELLA_ALLOW_REMOTE_WORKER_BASE_URL` | opcional (`=1`) | Permite o worker chamar um host não-loopback. |
|
|
144
|
+
| `CONSTELLA_WEB_HEAP_MB` | opcional | `--max-old-space-size` para o filho web. |
|
|
145
|
+
| `CONSTELLA_DEV` | opcional (`=1`) | Permite um fallback `next dev` a partir de uma árvore de fonte sem build. |
|
|
146
|
+
|
|
147
|
+
### Tabelas de tenancy + estruturais centrais (`src/db/schema.ts`)
|
|
148
|
+
|
|
149
|
+
| Tabela | Colunas-chave | Propósito |
|
|
150
|
+
| --- | --- | --- |
|
|
151
|
+
| `organization` | `id`, `ownerId`, `runMode` (`start\|auth\|vps\|portable`), `archived` | Tenant. `runMode` é o modo persistido. |
|
|
152
|
+
| `member` | `orgId`, `userId`, `role` (`owner\|admin\|member`) | Pertencimento à org + papéis. |
|
|
153
|
+
| `workspace` | `id`, `orgId`, `slug` (único), `stack` (JSON), `runMode`, `bootstrap`, `settings` (JSON) | Um workspace por org; `settings` guarda config de Telegram/GitHub/source/agents. |
|
|
154
|
+
| `agent` | `handle`, `role`, `adapter`, `model`, `status`, `health`, `reportsTo`, `dailyCapUsd` | A constelação de 10 agentes. |
|
|
155
|
+
| `skill` / `agentSkill` | `name`, `native`, `indexed`; junção `auto` | Procedimentos em Markdown + habilitação por agente. |
|
|
156
|
+
| `goal` / `spec` / `issue` / `task` / `plan` | ciclo de vida `status`/`col`, `approved`, `auto247` | O pipeline de trabalho ([GOALS_SPECS_ISSUES](./GOALS_SPECS_ISSUES.md)). |
|
|
157
|
+
| `message` / `chatSession` / `event` / `decision` | `channel`, `runId`, `seq` | Sala do Time, sessões de DM, eventos de run ao vivo, log de decisões. |
|
|
158
|
+
| `ragChunk` / `kbEntry` / `syncedBlock` / `docIndex` | embeddings + camada KB | Nebulosa de memória ([KB_RAG](./KB_RAG.md), [MEMORY_RAG](./MEMORY_RAG.md)). |
|
|
159
|
+
| `file` | `path`, `gitStatus` (`""\|M\|A\|U\|D`) | Espelho do editor + status porcelain do git. |
|
|
160
|
+
| `vault` | `ref`, `ciphertext`, `iv` | Segredos AES-GCM indexados por provider. |
|
|
161
|
+
| `fileLock` | `workspaceId+path` (PK), `taskId`, `heartbeatAt` | Lock por arquivo para que agentes em paralelo nunca editem o mesmo arquivo ([SECURITY](./SECURITY.md)). |
|
|
162
|
+
|
|
163
|
+
> O schema define ~60 tabelas. A lista acima cobre as que são estruturais para *arquitetura*; as tabelas de trabalho, KB e modelos são documentadas em suas próprias páginas.
|
|
164
|
+
|
|
165
|
+
### Motor de sincronização — prefixos indexados
|
|
166
|
+
|
|
167
|
+
`bin/worker.mjs` só encaminha arquivos que casam com o regex `INDEXED`; `src/server/sync.ts` então roteia cada caminho para um indexador por tipo:
|
|
168
|
+
|
|
169
|
+
| Padrão de caminho | Indexador | Alvo no banco |
|
|
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
|
+
Qualquer mudança em um arquivo RAG também agenda um re-embed incremental com debounce via `scheduleRagReindex`; uma deleção descarta seus chunks via `deindexRagFile`.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 🌌 Mermaid — o motor de sincronização (disco → banco)
|
|
182
|
+
|
|
183
|
+
```mermaid
|
|
184
|
+
sequenceDiagram
|
|
185
|
+
participant FS as Arquivos do workspace
|
|
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/>gate do regex INDEXED<br/>debounce 400ms por chave
|
|
193
|
+
W->>API: POST {orgId, rel, event}<br/>x-worker-secret
|
|
194
|
+
API->>API: 401 a menos que o segredo case
|
|
195
|
+
alt event = unlink
|
|
196
|
+
API->>SYNC: deindexFile(orgId, rel)
|
|
197
|
+
SYNC->>DB: deleta linha + descarta chunks RAG
|
|
198
|
+
else add / change
|
|
199
|
+
API->>SYNC: indexFile(orgId, rel)
|
|
200
|
+
SYNC->>SYNC: scheduleRagReindex(orgId, rel)
|
|
201
|
+
SYNC->>DB: upsert (disco vence) + revalidatePath
|
|
202
|
+
end
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 🛰️ Mermaid — o fluxo de prompt (tick → agente → disco → índice)
|
|
208
|
+
|
|
209
|
+
Este é o loop completo que transforma um tick autônomo em trabalho real no disco e de volta para a UI.
|
|
210
|
+
|
|
211
|
+
```mermaid
|
|
212
|
+
flowchart LR
|
|
213
|
+
T["tick do worker<br/>a cada 60s"] -->|"POST /api/cron/tick"| API["/api/cron/tick<br/>(401 sem x-worker-secret)"]
|
|
214
|
+
API --> RUN["tickAll({ execute:true, auto:true })"]
|
|
215
|
+
RUN -->|"por workspace ativo"| TW["tickWorkspace()"]
|
|
216
|
+
TW --> SPAWN["spawn claude / codex<br/>--output-format json<br/>cwd = workspace da org"]
|
|
217
|
+
SPAWN -->|"jaula FS safe()"| EDIT["agente edita arquivos"]
|
|
218
|
+
EDIT --> DISK[("workspace/ no disco")]
|
|
219
|
+
DISK -->|"chokidar"| WATCH["watcher do worker"]
|
|
220
|
+
WATCH -->|"POST /api/sync/file"| SYNC["indexFile()"]
|
|
221
|
+
SYNC --> DB[("índice SQLite")]
|
|
222
|
+
DB -->|"revalidatePath"| UI["UI Next.js atualiza"]
|
|
223
|
+
EDIT -.->|"linhas de event (runId, seq)"| DB
|
|
224
|
+
|
|
225
|
+
classDef store fill:#1a1a2e,stroke:#e0a44e,color:#fff
|
|
226
|
+
class DISK,DB store
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
O run do agente em si (modelo, modo de permissão, pesquisa web, timeouts) é detalhado em [AGENTS](./AGENTS.md) e [AI_ARCHITECTURE](./AI_ARCHITECTURE.md). Arquiteturalmente, o ponto-chave é o **loop fechado**: tick → spawn (CLI enjaulada) → disco → watcher → sync → banco → UI.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## 🚀 Passo a passo — rastreando uma única edição de ponta a ponta
|
|
234
|
+
|
|
235
|
+
1. O cron tick (ou um DM) avança um workspace; o runner faz spawn de um agente CLI com `cwd` = o workspace da org (a jaula FS).
|
|
236
|
+
2. O agente escreve um arquivo (ex.: `Reports/sprint-3.md`). Todas as escritas do código de servidor passam por `writeWorkspaceFile` → `safe()`; a própria CLI é confinada pelo `cwd` + os hooks de guarda/lock.
|
|
237
|
+
3. O chokidar (`awaitWriteFinish`, estabilidade de 300 ms) dispara `add`/`change`.
|
|
238
|
+
4. `parse(abs)` deriva `{orgId, rel}` de `<orgId>/workspace/<rel>` e testa o regex `INDEXED`. Arquivos não indexados são ignorados.
|
|
239
|
+
5. Um debounce de 400 ms por chave coalesce salvamentos rápidos, então `POST /api/sync/file` com `x-worker-secret`.
|
|
240
|
+
6. A rota autentica e chama `indexFile(orgId, rel)` → `indexReportFile` → upsert em `report`, mais `scheduleRagReindex`.
|
|
241
|
+
7. `revalidatePath("/reports")` (e `/code`) atualizam a UI na próxima navegação.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 🌠 Exemplos
|
|
246
|
+
|
|
247
|
+
**Boot via npm (modo start):**
|
|
248
|
+
```bash
|
|
249
|
+
npx constella # padrão = modo start, 127.0.0.1:3000
|
|
250
|
+
# Constella runtime root : C:\Users\voce\.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\voce\.constella\organizations
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Apontar a raiz de runtime para uma pasta de projeto (dev):**
|
|
257
|
+
```bash
|
|
258
|
+
CONSTELLA_HOME=./.constella npx constella --auth --port 4000
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Rodar web + worker juntos em desenvolvimento (sem instalação global):**
|
|
262
|
+
```bash
|
|
263
|
+
pnpm dev:all # scripts/dev-all.mjs → next dev + worker (poll do Telegram funciona em dev)
|
|
264
|
+
pnpm start # scripts/start-all.mjs → next start + worker (build de produção)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Inspecionar o índice diretamente:**
|
|
268
|
+
```bash
|
|
269
|
+
sqlite3 ~/.constella/constella.db ".tables"
|
|
270
|
+
sqlite3 ~/.constella/constella.db "SELECT handle,status,health FROM agent;"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 🕳️ Estados possíveis
|
|
276
|
+
|
|
277
|
+
| Superfície | Estados |
|
|
278
|
+
| --- | --- |
|
|
279
|
+
| Filho supervisionado | rodando · auto-reiniciando (`n/5 em 60s`) · desistiu (supervisor sai) |
|
|
280
|
+
| `organization.runMode` | `start` · `auth` · `vps` · `portable` |
|
|
281
|
+
| `workspace.runMode` | `off` · `start` · `auth` · `vps` · `portable` (`off` é excluído de `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
|
+
| Guarda de base URL do worker | loopback (permitido) · não-loopback + `ALLOW_REMOTE` · recusado (exit 1) |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## 🛰️ Integrações relacionadas
|
|
291
|
+
|
|
292
|
+
- **Endpoints do worker**: `/api/cron/tick`, `/api/sync/file`, `/api/telegram/poll` — todos atrás de `x-worker-secret`.
|
|
293
|
+
- **Telegram** long-poll roda dentro do worker → [TELEGRAM](./TELEGRAM.md).
|
|
294
|
+
- **GitHub** status do git flui para `file.gitStatus` → [GITHUB](./GITHUB.md).
|
|
295
|
+
- **RAG/KB** re-embedding é disparado pelo motor de sincronização → [KB_RAG](./KB_RAG.md), [MEMORY_RAG](./MEMORY_RAG.md).
|
|
296
|
+
- **Public API / MCP** são superfícies de entrada separadas (não usam o worker-secret) → [PUBLIC_API](./PUBLIC_API.md), [MCP](./MCP.md).
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## 🕳️ Segurança
|
|
301
|
+
|
|
302
|
+
- **Jaula FS** `safe()` — verificações léxica + de symlink; a raiz do workspace nunca é deletável através dela. O id da org é validado antes de qualquer caminho ser montado.
|
|
303
|
+
- **O segredo do worker falha fechado** — `/api/cron/tick` e `/api/sync/file` rejeitam toda requisição quando nenhum segredo está configurado (um segredo não definido *não* é uma porta aberta).
|
|
304
|
+
- **Guarda SSRF** — o worker só envia seu segredo para loopback a menos que sobrescrito explicitamente; uso remoto em texto-claro é avisado.
|
|
305
|
+
- **Vault** — os segredos vivem só na tabela `vault` (AES-256-GCM via `CONSTELLA_VAULT_KEY`), nunca nas linhas de provider; o `.env` é gravado `0o600`.
|
|
306
|
+
- **Escritor único** — o worker não tem handle de banco; todas as escritas passam pelo processo web, então há uma única autoridade para consistência.
|
|
307
|
+
- Detalhe completo em [SECURITY](./SECURITY.md).
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## 🌌 Solução de problemas
|
|
312
|
+
|
|
313
|
+
| Sintoma | Causa provável | Onde olhar |
|
|
314
|
+
| --- | --- | --- |
|
|
315
|
+
| Arquivo editado mas UI desatualizada | watcher não rodando, ou caminho fora de `INDEXED` | logs do worker (`watching …`); regex `INDEXED` em `bin/worker.mjs` |
|
|
316
|
+
| `401 unauthorized` no tick/sync | `CONSTELLA_WORKER_SECRET` divergente entre web + worker | `<HOME>/.env`; ambos os filhos o herdam do launcher |
|
|
317
|
+
| Worker sai no início | `CONSTELLA_BASE_URL` é não-loopback sem override | defina loopback ou `CONSTELLA_ALLOW_REMOTE_WORKER_BASE_URL=1` |
|
|
318
|
+
| Dois bancos separados aparecem | servidor standalone faz chdir sem `INIT_CWD` | use `pnpm start` / a CLI (eles definem `INIT_CWD`); veja o aviso em `src/lib/runtime-root.ts` |
|
|
319
|
+
| Banco novo sem tabelas | `drizzle-kit migrate` falhou no primeiro boot | reinstale o pacote; verifique se `drizzle/` é empacotado; o boot aborta numa falha de migrate em banco novo por design |
|
|
320
|
+
| Crash-loop "giving up" | um filho caiu 5× em 60s | veja a dica de OOM; suba `CONSTELLA_WEB_HEAP_MB` se for um OOM de heap JS |
|
|
321
|
+
|
|
322
|
+
Mais em [TROUBLESHOOTING](./TROUBLESHOOTING.md) e [FAQ](./FAQ.md).
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## ✦ Links relacionados
|
|
327
|
+
|
|
328
|
+
- [AI_ARCHITECTURE](./AI_ARCHITECTURE.md) — a camada cognitiva (agentes, RAG, contexto).
|
|
329
|
+
- [AGENTS](./AGENTS.md) — a constelação de 10 agentes e como os runs são iniciados.
|
|
330
|
+
- [CONFIGURATION](./CONFIGURATION.md) — variáveis de ambiente e configurações em profundidade.
|
|
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
|
+
[← Índice](./README.md) · [🇬🇧 English](../en/AUTH_MODE.md) · [✦ Constella](../../README.pt-BR.md)
|
|
2
|
+
|
|
3
|
+
# Modo Auth 🛰️
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
> Barreira real de e-mail + senha na frente da nave central — para quando mais de um humano compartilha a mesma máquina, mas você ainda quer um plano de controle privado, restrito ao loopback.
|
|
8
|
+
|
|
9
|
+
O modo Auth é o run mode em que toda sessão precisa passar por uma barreira de credencial. Diferente do modo `start` (que cria e autentica automaticamente um operador local), o modo `auth` exibe a tela de login real, assina as sessões com um `BETTER_AUTH_SECRET` obrigatório e suporta 2FA por TOTP e passkeys WebAuthn. Ele continua escutando em `127.0.0.1`, então a superfície é a mesma órbita local do `start` — apenas a porta da frente fica trancada.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ✦ Quando usar
|
|
14
|
+
|
|
15
|
+
Use o modo `auth` quando:
|
|
16
|
+
|
|
17
|
+
- Uma **estação compartilhada** hospeda o Constella e você não quer que qualquer pessoa com acesso físico entre direto no app.
|
|
18
|
+
- Você quer uma **conta real** (e-mail + senha, opcionalmente 2FA / passkey) em vez da conta auto-provisionada `operator@constella.dev`.
|
|
19
|
+
- Você quer assinatura de sessão com um **segredo persistido**, mas ainda quer manter o listener no loopback (sem exposição de rede).
|
|
20
|
+
|
|
21
|
+
Escolha outro modo quando:
|
|
22
|
+
|
|
23
|
+
| Você quer… | Use |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Local sem fricção, usuário único, sem login | [START_MODE](./START_MODE.md) |
|
|
26
|
+
| Acesso remoto por uma tailnet privada, em Docker | [VPS_MODE](./VPS_MODE.md) |
|
|
27
|
+
| Todo o runtime carregado em um pen-drive USB | [PORTABLE_MODE](./PORTABLE_MODE.md) |
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🌌 Como funciona
|
|
32
|
+
|
|
33
|
+
`auth` é um dos quatro valores de `RunMode` definidos em `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
|
+
O modo é selecionado pela flag de launch em `bin/constella.mjs` e exportado para o ambiente como `CONSTELLA_RUN_MODE`. O servidor o lê de volta com `getRunMode()`; `requiresLogin()` retorna `true` para `auth`.
|
|
47
|
+
|
|
48
|
+
Três pilares definem o modo:
|
|
49
|
+
|
|
50
|
+
1. **`requiresLogin: true`** — `requireWorkspace()` (em `src/lib/workspace.ts`) envia uma requisição não autenticada para `/login`, não para `/api/dev-login`. Não há login automático.
|
|
51
|
+
2. **`BETTER_AUTH_SECRET` obrigatório** — todo modo com capacidade de rede (`auth`, `vps`, `portable`) precisa subir com um segredo de assinatura real ou se recusa a servir (veja [Segurança](#-segurança)).
|
|
52
|
+
3. **Bind em `127.0.0.1`** — `auth` mantém o mesmo host de loopback do `start`; apenas `vps` e `portable` fazem bind em `0.0.0.0`.
|
|
53
|
+
|
|
54
|
+
### A superfície de login (`better-auth`)
|
|
55
|
+
|
|
56
|
+
`src/lib/auth.ts` configura o `better-auth` com:
|
|
57
|
+
|
|
58
|
+
- **E-mail + senha** sempre habilitados (`emailAndPassword: { enabled: true, autoSignIn: true, requireEmailVerification: false }`).
|
|
59
|
+
- **2FA por TOTP** via plugin `twoFactor()` (Profile → Security).
|
|
60
|
+
- **Passkeys WebAuthn** via rotas customizadas `/api/passkey/*` construídas sobre `@simplewebauthn` (o formulário de login oferece um botão de passkey).
|
|
61
|
+
- **Provedores sociais** (GitHub / Google) apenas quando as credenciais de ambiente estão presentes — usados para vinculação de conta, não como caminho de auth primário.
|
|
62
|
+
- **Sessões de 30 dias** (`expiresIn: 60 * 60 * 24 * 30`).
|
|
63
|
+
- **Cookies Secure** sempre que a base URL for `https://` (`useSecureCookies: BASE_URL.startsWith("https://")`). No `auth` puro sobre http local, os cookies ficam relaxados; atrás de um reverse proxy https eles viram `Secure`.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🚀 Fluxo principal
|
|
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() persiste<br/>BETTER_AUTH_SECRET em ~/.constella/.env"]
|
|
73
|
+
C --> D["boot.ts → assertAuthSecret()"]
|
|
74
|
+
D -->|segredo presente| E["servidor serve"]
|
|
75
|
+
D -->|segredo ausente| X["process.exit(1)"]
|
|
76
|
+
E --> F["browser acessa qualquer página (app)"]
|
|
77
|
+
F --> G["requireWorkspace()"]
|
|
78
|
+
G -->|sem sessão| H["redirect /login"]
|
|
79
|
+
H --> I["LoginForm: e-mail + senha"]
|
|
80
|
+
I -->|2FA habilitado| J["código TOTP → verifyTotp"]
|
|
81
|
+
I -->|passkey| K["/api/passkey/authenticate"]
|
|
82
|
+
J --> L["cookie de sessão definido · redirect /"]
|
|
83
|
+
K --> L
|
|
84
|
+
I -->|senha ok, sem 2FA| L
|
|
85
|
+
G -->|sessão ok| M["workspace escopado retornado"]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 🪐 Conceitos-chave
|
|
91
|
+
|
|
92
|
+
| Conceito | Onde | Significado |
|
|
93
|
+
|---|---|---|
|
|
94
|
+
| `RunMode` | `src/lib/run-mode.ts` | `"auth"` é um dos quatro modos; governa login + comportamento de bind. |
|
|
95
|
+
| `requiresLogin()` | `src/lib/run-mode.ts` | Retorna `true` para `auth` — o app exige uma credencial. |
|
|
96
|
+
| `assertAuthSecret()` | `src/lib/auth.ts` | Barreira rígida de boot: recusa rodar um modo de rede sem `BETTER_AUTH_SECRET`. |
|
|
97
|
+
| `requireWorkspace()` | `src/lib/workspace.ts` | Guard por página; redireciona requisições `auth` não autenticadas para `/login`. |
|
|
98
|
+
| `LoginForm` | `src/app/(auth)/login/login-form.tsx` | UI de e-mail/senha + 2FA + passkey. |
|
|
99
|
+
| `auth` (better-auth) | `src/lib/auth.ts` | O servidor de auth configurado (e-mail/senha, 2FA, social, sessões). |
|
|
100
|
+
| `createSessionCookie()` | `src/server/passkey-login.ts` | Emite uma sessão real do better-auth após uma asserção de passkey. |
|
|
101
|
+
| `member.role` | `src/db/schema.ts` | `owner` \| `admin` \| `member` — papéis de membro da organização. |
|
|
102
|
+
|
|
103
|
+
### `auth` vs `start` — o contraste
|
|
104
|
+
|
|
105
|
+
`start` e `auth` compartilham o mesmo host de loopback e o mesmo runtime de processo duplo; eles diferem inteiramente na **porta da frente**.
|
|
106
|
+
|
|
107
|
+
| Dimensão | `start` | `auth` |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `requiresLogin` | `false` | `true` |
|
|
110
|
+
| Tela de login | pulada | exibida (`/login`) |
|
|
111
|
+
| Conta | auto-provisionada `operator@constella.dev` / `operator123` | uma conta real que você cria/acessa |
|
|
112
|
+
| Login automático | sim — `/api/dev-login` | não |
|
|
113
|
+
| `BETTER_AUTH_SECRET` | persistido, mas não estritamente exigido por `assertAuthSecret()` | **obrigatório** (boot recusa sem ele) |
|
|
114
|
+
| Host de bind | `127.0.0.1` | `127.0.0.1` |
|
|
115
|
+
| 2FA / passkeys | disponíveis mas inúteis (login automático) | o propósito do modo |
|
|
116
|
+
| Seguro em máquina compartilhada? | não (quem tem a máquina, entra) | sim (barreira de credencial) |
|
|
117
|
+
| `ensureLocalOperator()` | chamado | lança exceção — "start-mode only" |
|
|
118
|
+
|
|
119
|
+
A credencial previsível `operator/operator123` é provisionada **apenas** no modo `start`. `ensureLocalOperator()` (em `src/server/dev-auth.ts`) lança explicitamente uma exceção se `getRunMode() !== "start"`, então um modo de rede nunca carrega um login remoto padrão.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🌠 Passo a passo
|
|
124
|
+
|
|
125
|
+
### 1. Lance no modo auth
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npx constella --auth
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`bin/constella.mjs` define `CONSTELLA_RUN_MODE=auth`, escolhe `host = 127.0.0.1` (apenas `vps`/`portable` usam `0.0.0.0`), e `port` por padrão é `3000` (sobrescreva com `--port`).
|
|
132
|
+
|
|
133
|
+
### 2. Segredos são persistidos
|
|
134
|
+
|
|
135
|
+
A cada launch, `bin/constella.mjs` garante que três segredos existam sob o runtime root e os grava (modo `0o600`) em `~/.constella/.env`:
|
|
136
|
+
|
|
137
|
+
| Segredo | Propósito |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `BETTER_AUTH_SECRET` | Assina cookies de sessão (obrigatório em `auth`). |
|
|
140
|
+
| `CONSTELLA_VAULT_KEY` | Chave AES-256-GCM para o cofre de segredos de provedores. |
|
|
141
|
+
| `CONSTELLA_WORKER_SECRET` | Segredo compartilhado que o worker apresenta ao web (`x-worker-secret`). |
|
|
142
|
+
|
|
143
|
+
`ensureSecret()` reutiliza um valor persistido existente, prefere um override de ambiente e, caso contrário, gera um uma única vez. Persistir (não regerar) significa que suas sessões de login e o cofre criptografado sobrevivem a um restart.
|
|
144
|
+
|
|
145
|
+
### 3. A barreira de boot dispara
|
|
146
|
+
|
|
147
|
+
Na primeira requisição, `reconcileOnBoot()` (em `src/server/boot.ts`) chama `assertAuthSecret()` **antes de qualquer outra coisa**. No `auth` sem um segredo real, o processo registra `[boot] FATAL:` e chama `process.exit(1)` — o servidor nunca serve um cookie forjável.
|
|
148
|
+
|
|
149
|
+
### 4. Faça login
|
|
150
|
+
|
|
151
|
+
O browser acessa qualquer página `(app)` → `requireWorkspace()` não encontra sessão → redireciona para `/login`. O `LoginForm`:
|
|
152
|
+
|
|
153
|
+
- Pré-preenche `operator@constella.dev`, mas aceita qualquer e-mail.
|
|
154
|
+
- Chama `signIn.email({ email, password })`. Se o e-mail for desconhecido, recai em `signUp.email(...)` (criação no primeiro login).
|
|
155
|
+
- O botão de submit fica desabilitado até a senha ter pelo menos 8 caracteres.
|
|
156
|
+
|
|
157
|
+
### 5. Segundo fator opcional
|
|
158
|
+
|
|
159
|
+
- **2FA por TOTP:** se habilitado, `signIn.email` retorna `twoFactorRedirect`; o formulário troca para um campo de código de 6 dígitos e chama `authClient.twoFactor.verifyTotp({ code })`.
|
|
160
|
+
- **Passkey:** o botão de "passkey" faz POST para `/api/passkey/authenticate/options`, executa `startAuthentication(...)` no browser, e então faz POST da asserção para `/api/passkey/authenticate/verify`. Em caso de sucesso, o servidor emite um cookie de sessão real via `createSessionCookie()`.
|
|
161
|
+
|
|
162
|
+
### 6. Gerenciar segundos fatores (Profile → Security)
|
|
163
|
+
|
|
164
|
+
- **Habilitar 2FA:** `authClient.twoFactor.enable({ password })` → escaneie a URI TOTP → `verifyTotp({ code })`. Desabilite com `authClient.twoFactor.disable({ password })`.
|
|
165
|
+
- **Passkeys:** registradas via rotas `/api/passkey/register/*`; gerenciadas (renomear / remover) por `removePasskey` / ações de renomear em `src/server/actions/profile-actions.ts`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 🕳️ Exemplos
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# Launch padrão do modo auth na porta padrão
|
|
173
|
+
npx constella --auth
|
|
174
|
+
|
|
175
|
+
# Modo auth em uma porta customizada
|
|
176
|
+
npx constella --auth --port 4000
|
|
177
|
+
|
|
178
|
+
# Modo auth com o runtime root em outro lugar
|
|
179
|
+
npx constella --auth --path /srv/constella-home
|
|
180
|
+
|
|
181
|
+
# Forçar o assistente de onboarding de primeira execução, ainda sob a barreira auth
|
|
182
|
+
npx constella --auth --onboarding
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
> O **seletor** de run mode na tela de login aparece apenas no modo desenvolvedor (`isDevMode()` em `src/lib/build-mode.ts`). Um launch público pelo CLI define `CONSTELLA_PUBLIC=1`, então o modo é fixado pela flag de launch e o seletor fica oculto.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## ✦ Estados possíveis
|
|
190
|
+
|
|
191
|
+
| Estado | Causa | Sintoma |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| **Login obrigatório** | Modo `auth`, sem sessão | Browser redirecionado para `/login`. |
|
|
194
|
+
| **Senha rejeitada** | Senha errada para uma conta existente | Mensagem `login.failed`; sem fallback para signup (e-mail existe). |
|
|
195
|
+
| **Nova conta criada** | E-mail desconhecido + senha válida | `signUp.email` tem sucesso, redirect para `/`. |
|
|
196
|
+
| **Desafio 2FA** | Conta com TOTP habilitado | Campo de código exibido; precisa de um TOTP de 6 dígitos. |
|
|
197
|
+
| **Login por passkey** | Usuário clica no botão de passkey | Prompt WebAuthn do browser; sessão emitida no servidor. |
|
|
198
|
+
| **Boot recusado** | Modo de rede, `BETTER_AUTH_SECRET` ausente | `[boot] FATAL` + `process.exit(1)`; servidor nunca inicia. |
|
|
199
|
+
| **Login automático tentado** | `ensureLocalOperator` alcançado em `auth` | Lança `"ensureLocalOperator is start-mode only"` (defesa em profundidade). |
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 🛰️ Integrações relacionadas
|
|
204
|
+
|
|
205
|
+
- **Isolamento de organização** — após o login, `requireWorkspace()` resolve a org ativa por meio de um join em `member`, então uma sessão nunca aponta para a org de outro tenant (`getActiveOrg` em `src/lib/workspace.ts`). Papéis são `owner` / `admin` / `member`.
|
|
206
|
+
- **Cofre (Vault)** — segredos de provedores são criptografados com `CONSTELLA_VAULT_KEY`, persistidos junto de `BETTER_AUTH_SECRET` em `~/.constella/.env`. Veja [SECURITY](./SECURITY.md).
|
|
207
|
+
- **Worker** — o worker 24/7 se autentica ao web com `x-worker-secret` (`CONSTELLA_WORKER_SECRET`) sobre loopback, independente do login humano. Veja [ARCHITECTURE](./ARCHITECTURE.md).
|
|
208
|
+
- **API Pública / PAT** — acesso programático usa PATs `Bearer cn_<token>`, um caminho separado da sessão do browser. Veja [PUBLIC_API](./PUBLIC_API.md).
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 🕳️ Segurança
|
|
213
|
+
|
|
214
|
+
- **Segredo de assinatura obrigatório.** `auth` (assim como `vps`/`portable`) **precisa** subir com um `BETTER_AUTH_SECRET` real. Sem ele, as sessões seriam assinadas com a chave padrão pública do better-auth (cookies forjáveis), porque o better-auth só lança exceção na chave padrão sob `NODE_ENV=production`. `assertAuthSecret()` fecha essa brecha encerrando o processo. `start` é isento por ser local-only com login automático.
|
|
215
|
+
- **Bind no loopback.** `auth` faz bind em `127.0.0.1`; o listener não é alcançável pela rede. Se você colocar um reverse proxy https na frente, defina `BETTER_AUTH_URL` para a origem pública `https://` para que os cookies de sessão sejam marcados como `Secure`.
|
|
216
|
+
- **Sem credencial remota padrão.** A conta `operator/operator123` é exclusiva do modo start e nunca é provisionada em `auth`.
|
|
217
|
+
- **2FA / passkeys reais.** Segredos TOTP vivem na tabela `two_factor`; credenciais WebAuthn na tabela `passkey` (chave pública COSE, counter, transports). Desafios de passkey são guardados em cookies httpOnly de vida curta (`maxAge: 300`) entre os round-trips de options e verify (`src/lib/passkey.ts`).
|
|
218
|
+
- **Sessões de 30 dias.** Sessões expiram após 30 dias; o caminho de exclusão de `account` faz cascade para sessões, contas, passkeys e tokens.
|
|
219
|
+
- **Segurança entre tenants.** `activeOrgId` é tratado como controlável por atacante e sempre revalidado por meio de um join de membership.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 🌌 Solução de problemas
|
|
224
|
+
|
|
225
|
+
| Sintoma | Causa provável | Correção |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| Servidor encerra imediatamente com `[boot] FATAL: BETTER_AUTH_SECRET is required` | Modo de rede subiu sem segredo | Deixe o CLI persistir um (padrão), ou defina `BETTER_AUTH_SECRET` no ambiente / `~/.constella/.env`. |
|
|
228
|
+
| Tela de login nunca aparece (já autenticado) | Você na verdade lançou `start`, não `auth` | Confira a linha de boot `Mode : auth · 127.0.0.1:3000`; relance com `--auth`. |
|
|
229
|
+
| "ensureLocalOperator is start-mode only" nos logs | Caminho de login automático alcançado sob `auth` | Guard esperado — não há login automático em `auth`; faça login manualmente. |
|
|
230
|
+
| Botão de passkey falha | Host de `BETTER_AUTH_URL` divergente (RP id) | Defina `BETTER_AUTH_URL` para a origem exata pela qual você navega; `rpID()` é o hostname dela. |
|
|
231
|
+
| Cookies não `Secure` atrás de https | `BASE_URL` ainda é `http://localhost:3000` | Defina `BETTER_AUTH_URL` para a origem `https://` para que `useSecureCookies` ative. |
|
|
232
|
+
| Esqueceu a senha do operador (migração start→auth) | A credencial padrão só existe em `start` | Em `auth`, crie/acesse uma conta real; não dependa de `operator123`. |
|
|
233
|
+
| Não consegue alcançar o app de outra máquina | `auth` faz bind no loopback por design | Use [VPS_MODE](./VPS_MODE.md) para acesso remoto. |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## ✦ Links relacionados
|
|
238
|
+
|
|
239
|
+
- [START_MODE](./START_MODE.md) — o modo local de login automático com que o `auth` contrasta.
|
|
240
|
+
- [VPS_MODE](./VPS_MODE.md) — modo exposto à rede sobre uma tailnet, em Docker.
|
|
241
|
+
- [PORTABLE_MODE](./PORTABLE_MODE.md) — o run mode de pen-drive USB.
|
|
242
|
+
- [CONFIGURATION](./CONFIGURATION.md) — variáveis de ambiente, segredos e o runtime root.
|
|
243
|
+
- [INSTALLATION](./INSTALLATION.md) — instalação e primeiro launch.
|
|
244
|
+
- [SECURITY](./SECURITY.md) — cofre, scrubbing, jail de FS, modelo de sessão.
|
|
245
|
+
- [ARCHITECTURE](./ARCHITECTURE.md) — processo duplo web + worker, reconcile de boot.
|
|
246
|
+
- [PUBLIC_API](./PUBLIC_API.md) — acesso programático baseado em PAT.
|
|
247
|
+
- [TROUBLESHOOTING](./TROUBLESHOOTING.md) — catálogo de falhas mais amplo.
|