WorkSuite kanban
  • Go 47.9%
  • TypeScript 45.9%
  • Astro 4.4%
  • Makefile 0.7%
  • JavaScript 0.5%
  • Other 0.6%
Find a file
arcanedemesne 28b3e620d2
Some checks are pending
CI / test (push) Waiting to run
CI / frontend (push) Waiting to run
Deploy stage / deploy (push) Waiting to run
Add dev/stage/prod env support
2026-07-15 00:11:06 -04:00
.forgejo/workflows Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
backend Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
docs Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
frontend Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
nginx Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
.env.example Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
.env.stage.example Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
.gitignore initial commit 2026-07-06 12:49:19 -04:00
.golangci.yml Refactor to use new @arcanedemesne/* compnents 2026-07-14 13:53:14 -04:00
authentik.bootstrap.yaml Add org/project/team membership APIs (rosters, deactivation, invites, atomic patches), seed example project/team on org create, and ship entity views with member modals, invite accept, profile pages, and modal/navigation fixes on the frontend. 2026-07-07 21:44:54 -04:00
authentik.sync.yaml Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
compose.prod.yml Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
compose.stage.yml Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
compose.yml Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
go.work Refactor to use new @arcanedemesne/* compnents 2026-07-14 13:53:14 -04:00
Makefile Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
nginx.conf Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00
README.md Add dev/stage/prod env support 2026-07-15 00:11:06 -04:00

ArcaneDemesne WorkSuite

Go BFF API + Astro frontend for multi-tenant project management. Edge nginx on host 8084; API 5084; Astro 4084. Production: https://worksuite.arcanedemesne.com via Gateway.

Port matrix: Gateway/PORT_MATRIX.md

Compose

Requires gateway-hub (edge only) and authentik-net (API OIDC + SMTP to mailpit) — create once from Gateway. Never put api/app on gateway-hub.

cp .env.example .env   # fill AUTH_SESSION_SECRET, AUTH_OIDC_*, etc.
make up

Production (auth.arcanedemesne.com authority, tier-2 ports):

cp .env.example .env.prod
# Tier 2: WORKSUITE_*_PORT 8284/5284/4284/6284; AUTH_OIDC_AUTHORITY=https://auth.arcanedemesne.com/...
# INVITE_WEB_URL=https://worksuite.arcanedemesne.com
make up-prod

Stage (stage.worksuite.arcanedemesne.com, tier-1 ports):

cp .env.stage.example .env.stage
make up-stage
make migrate-up-stage

Env files

File Use
.env.example Dev Podman (worksuite-dev, tier-0 ports)
.env Local dev stack (make up)
.env.stage.example Stage template (worksuite-stage)
.env.stage Stage stack (make up-stage)
.env.prod Production stack (make up-prod, project worksuite)
backend/.env.local Host split-port dev (make run, bun dev)

Authentik: make authentik-bootstrap, docs/SSO.md.

Local dev (host, split ports)

Process Directory Env file URL
Go API backend/ .env.local (from .env.example) http://localhost:5084
Astro frontend/worksuite/ src/.env.development.local http://localhost:4084
# Terminal 1 — from backend/
cp .env.example .env.local   # fill AUTH_* (localhost:9000 Authentik)
make run

# Terminal 2 — from frontend/worksuite/
bun dev

Register Authentik URIs for split-port dev:

  • OIDC callback (API): http://localhost:5084/sign-in-oidc
  • Post-logout (Astro): http://localhost:4084/sign-out

Via edge nginx: http://localhost:8084 (same-origin API + app).

Auth

OIDC BFF via shared Packages/authentication. Root .env.example for compose; backend/.env.example for host dev. Cookie name per tier: worksuite-auth-dev / -stage / -prod.

Full Authentik app setup: docs/SSO.md.

Go modules: no vendor/. Local dev uses go.work. Shared packages use replace in go.mod until Forgejo serves correct go-import meta tags.

Container build uses monorepo context (ArcaneDemesne/) — see backend/Dockerfile.

Migrations

One migration set for all tiers: backend/migrations/. Each tier has its own Postgres volume — run migrations after Postgres is up.

Tier Postgres (host) Migrate
dev / local 6084 make migrate-up (backend/.env.local)
stage 6184 make migrate-up-stage
prod 6284 make migrate-up-prod
make migrate-up          # dev
make migrate-up-stage    # after make up-stage
make migrate-up-prod     # after make up-prod
make migrate-down        # rollback one step (dev)

After recreating API/app containers, reload edge: make proxy-reload-dev, proxy-reload-stage, or proxy-reload-prod.

Forgejo stage deploy: .forgejo/workflows/deploy-stage.yaml.

DATABASE_URL must include timezone=UTC (see backend/.env.example).

Build

make build         # Podman compose build
# From backend/
make -C backend build

# Workspace tests (backend + shared packages)
make test

Frontend routes

Page Path
Organizations /organizations — list, members/invites modal, modal CRUD
All projects /organizations/all/projects — projects across all your orgs
Projects /organizations/{organizationId}/projects — list, edit modal, roster modal
All teams (global) /organizations/all/projects/all/teams — teams across all orgs and projects
Org all teams /organizations/{organizationId}/projects/all/teams — teams across projects in one org
Teams /organizations/{organizationId}/projects/{projectId}/teams — project-scoped grid; .../teams/{teamId} deep-links team edit
Org teams shortcut /organizations/{organizationId}/teams — redirects to org all teams
Invites /invites/accept?token= — accept org invitation
Board /organizations/{organizationId}/projects/{projectId}/board — Kanban
Org board shortcut /organizations/{organizationId}/board — redirects to first project's board

Reserved URL segment all (not a UUID) means aggregate scope in org/project filters. Header Projects and Teams default to the All views.

Creating an organization also seeds an example project and example team (names include org/project context) in the same transaction. Production: org create requires worksuite-admins when WORKSUITE_ALLOW_ORG_CREATE=false; join via invite accept.

Members, teams, and invites

Flow Rule
Join org Invite accept (organization_invites.roleorganization_members.role)
Project roster Add org members to project first
Team roster Pick from project members only; optional team membership
Remove from project Cascades team membership for that project

UI: Members on /organizations; Roster on projects grid + Manage roster in project edit modal; Teams in header nav with org/project filters and Members per team row.

API routes

Resource Path Auth
Health /api/v1/health Public
Profile /api/v1/me/profile Session required
My organizations GET /api/v1/organizations/mine Session required
My projects GET /api/v1/organizations/mine/projects Session required
My teams GET /api/v1/organizations/mine/teams Session required
Organizations /api/v1/organizations Session (POST create); org member (read/update/delete)
Members /api/v1/organizations/{organizationId}/members Org member
Invites /api/v1/organizations/{organizationId}/invites Lead/Manager send; Lead/Manager revoke
Accept invite POST /api/v1/invites/accept Session + matching email
My invites GET /api/v1/invites/mine Session
Org all teams GET /api/v1/organizations/{organizationId}/projects/teams Org member
Teams /api/v1/organizations/{organizationId}/projects/{projectId}/teams Org member
Projects /api/v1/organizations/{organizationId}/projects Org member
Features /api/v1/organizations/{organizationId}/projects/{projectId}/features Org member
Work items /api/v1/organizations/{organizationId}/projects/{projectId}/work-items Org member
Work item by number GET .../work-items/by-number/{number} Org member
Tasks /api/v1/organizations/{organizationId}/projects/{projectId}/work-items/{workItemId}/tasks Org member

Org-scoped RBAC uses tier-based permissions in internal/authz/ (OWNER / MANAGER / EMPLOYEE).