- Implemented JWT-based authentication with signup, login, bearer token support, and HttpOnly auth cookies.
- Added protected route handling through authentication middleware and context helpers for user ID and email.
- Added stricter CORS configuration with explicit allowed-origin validation.
- Built workspace management APIs for creating, listing, viewing, updating, and deleting workspaces.
- Added workspace membership tracking so access can be enforced by role instead of ownership alone.
- Built decision management APIs inside workspaces for create, list, view, update, and delete flows.
- Added invitation workflows so workspace owners can invite members by email, validate invitations, accept invitations, and cancel pending invitations.
- Added member management APIs so owners can list members, change roles, remove members, and transfer ownership.
- Built integrations infrastructure for Slack and GitHub, including OAuth entry points, callback handling, connection status, integration listing, and disconnect flows.
- Added GitHub repository sync support and a background sync service for provider integrations.
- Added signal APIs for listing signals, filtering by source and status, viewing individual signals, and updating read/archive state.
- Added GitHub webhook ingestion support for inbound repository activity.
- Expanded the SQLite schema to support workspaces, members, invitations, integrations, signals, signal status, and decisions.
- Added backend unit tests across handlers, middleware, services, and utilities.
- Connected the Angular frontend to the live backend APIs for authentication, workspaces, decisions, integrations, members, invitations, and signals.
- Added invitation acceptance UI and related test coverage.
- Added workspace member management UI and related test coverage.
- Added search UI and search service coverage for signals, decisions, and workspace-aware results.
- Added Angular unit tests across components, guards, and services.
- Added a Cypress login smoke test.
src/app/app.component.spec.ts- App shell creation and basic bootstrap behavior.
src/app/components/accept-invitation/accept-invitation.spec.ts- Invitation validation, acceptance flow, and auth-aware behavior.
src/app/components/dashboard/dashboard.spec.ts- Dashboard initialization, workspace loading, and logout behavior.
src/app/components/login/login.spec.ts- Login and signup validation, service calls, and error handling.
src/app/components/workspace-integrations/workspace-integrations.spec.ts- Slack and GitHub integration UI behavior, sync actions, and selection persistence.
src/app/components/workspace-members/workspace-members.spec.ts- Member listing, invitations, role updates, and member removal flows.
src/app/guards/auth-guard.spec.ts- Route protection for authenticated and unauthenticated users.
src/app/services/integration.service.spec.ts- Integration API request behavior and response mapping.
src/app/services/search.service.spec.ts- Search aggregation behavior for signals, decisions, and workspaces.
src/app/services/signal.service.spec.ts- Signal loading and action behavior.
src/app/services/workspace-member.service.spec.ts- Workspace member and invitation service calls.
src/app/services/workspace.spec.ts- Workspace service CRUD request behavior.
cypress/e2e/login.cy.ts- Verifies the login flow as a frontend smoke test.
handlers/auth_test.go- Covers signup, signin, invalid email handling, and secure cookie behavior in production mode.
handlers/integrations_test.go- Covers Slack and GitHub OAuth state validation, callback validation, workspace-filtered integrations, deletion permissions, and integration status responses.
handlers/invitations_test.go- Covers invitation lifecycle, listing and canceling invitations, ownership transfer, token generation, and path helper behavior.
handlers/signals_test.go- Covers resolved signal status behavior for signal lists and workspace-scoped totals.
handlers/workspaces_test.go- Covers workspace CRUD lifecycle and workspace decision lifecycle.
middleware/auth_test.go- Covers bearer token auth, cookie auth, missing tokens, and malformed token rejection.
middleware/cors_test.go- Covers allowed origins, disallowed origins, preflight handling, and invalid origin configuration.
middleware/roles_test.go- Covers workspace role fallback and role-based access helpers.
services/github_test.go- Covers GitHub issue and pull request splitting logic.
services/sync_test.go- Covers Slack sync deduplication, metadata updates, and safe handling of Slack
not_in_channelerrors.
- Covers Slack sync deduplication, metadata updates, and safe handling of Slack
utils/encryption_test.go- Covers token encryption and key padding behavior.
utils/validation_test.go- Covers email validation logic.
Base URL: http://localhost:8080
Auth notes:
- Protected routes require JWT authentication.
- The backend accepts either a bearer token or the auth cookie set during login.
- Most protected routes return
401 Unauthorizedwhen auth is missing or invalid.
- Description: Creates a new user account.
- Auth: No
- Request body:
{
"email": "user@example.com",
"password": "password123"
}- Success:
201 Created
- Common errors:
400 Bad Requestfor invalid JSON or invalid email format409 Conflictif the email already exists
- Description: Signs in a user and returns a JWT token in JSON while also setting an auth cookie.
- Auth: No
- Request body:
{
"email": "user@example.com",
"password": "password123"
}- Success:
200 OK
{
"token": "jwt-token"
}- Common errors:
400 Bad Requestfor invalid JSON or invalid email401 Unauthorizedfor invalid credentials500 Internal Server Errorfor missing server JWT configuration
- Description: Simple authenticated route used to verify auth wiring.
- Auth: Yes
- Success:
200 OK- Plain-text greeting response
- Description: Lists workspaces where the authenticated user is a member.
- Auth: Yes
- Success:
200 OK
- Description: Creates a workspace and automatically adds the creator as owner.
- Auth: Yes
- Request body:
{
"name": "Platform",
"description": "Platform engineering workspace"
}- Success:
201 Created
- Common errors:
400 Bad Requestfor invalid JSON or blank name500 Internal Server Errorif workspace or membership creation fails
- Description: Returns one workspace if the authenticated user is a member.
- Auth: Yes
- Success:
200 OK
- Common errors:
400 Bad Requestfor invalid workspace ID403 Forbiddenif the user is not a member404 Not Found
- Description: Updates a workspace's name and description.
- Auth: Yes
- Authorization: Owner only
- Request body:
{
"name": "Platform Team",
"description": "Updated workspace description"
}- Success:
200 OK
- Common errors:
400 Bad Request403 Forbidden404 Not Found
- Description: Deletes a workspace and related records.
- Auth: Yes
- Authorization: Owner only
- Success:
204 No Content
- Common errors:
400 Bad Request403 Forbidden
- Description: Lists decisions for a workspace.
- Auth: Yes
- Authorization: Any workspace member
- Success:
200 OK
- Description: Creates a decision in a workspace.
- Auth: Yes
- Authorization: Owner or member
- Request body:
{
"title": "Choose notification strategy",
"description": "Decide how alerts should be prioritized",
"status": "OPEN",
"due_date": "2026-04-01T00:00:00Z"
}- Success:
201 Created
- Common errors:
400 Bad Requestfor invalid JSON or invalid fields403 Forbidden
- Description: Returns one decision in a workspace.
- Auth: Yes
- Authorization: Any workspace member
- Success:
200 OK
- Common errors:
400 Bad Request403 Forbidden404 Not Found
- Description: Updates a decision.
- Auth: Yes
- Authorization: Owner or member
- Request body:
{
"title": "Choose notification strategy",
"description": "Updated decision context",
"status": "CLOSED",
"due_date": null
}- Success:
200 OK
- Common errors:
400 Bad Request403 Forbidden404 Not Found
- Description: Deletes a decision.
- Auth: Yes
- Authorization: Owner or member
- Success:
204 No Content
- Common errors:
400 Bad Request403 Forbidden404 Not Found
- Description: Creates a workspace invitation for an email address.
- Auth: Yes
- Authorization: Owner only
- Request body:
{
"email": "teammate@example.com",
"role": "member"
}- Success:
201 Created
- Common errors:
400 Bad Requestfor invalid workspace ID, invalid JSON, or invalid email403 Forbidden409 Conflictif the user is already a member or an active invitation exists
- Description: Lists active invitations for a workspace.
- Auth: Yes
- Authorization: Owner only
- Success:
200 OK
- Description: Cancels a pending invitation.
- Auth: Yes
- Authorization: Owner only
- Success:
204 No Content
- Common errors:
400 Bad Request403 Forbidden404 Not Found
- Description: Validates an invitation token and returns invitation metadata.
- Auth: No
- Success:
200 OK
{
"valid": true,
"workspace": {
"id": 1,
"name": "Platform"
},
"invited_by": {
"email": "owner@example.com"
},
"role": "member",
"expires_at": "2026-04-01T00:00:00Z"
}- Common errors:
400 Bad Request404 Not Found410 Goneif expired
- Description: Accepts an invitation for the currently authenticated user.
- Auth: Yes
- Success:
200 OK
{
"workspace_id": 1,
"role": "member"
}- Common errors:
400 Bad Request403 Forbiddenif the logged-in email does not match the invitation404 Not Found409 Conflictif already a member410 Goneif expired
- Description: Lists members in a workspace.
- Auth: Yes
- Authorization: Any workspace member
- Success:
200 OK
- Description: Updates a member role or transfers ownership.
- Auth: Yes
- Authorization: Owner only
- Request body:
{
"role": "viewer"
}- Success:
200 OK
- Common errors:
400 Bad Requestfor invalid IDs, invalid JSON, or invalid role403 Forbidden404 Not Found
- Description: Removes a member from a workspace.
- Auth: Yes
- Authorization: Owner only
- Success:
204 No Content
- Common errors:
400 Bad Request403 Forbidden404 Not Found
- Description: Lists integrations for the authenticated user.
- Auth: Yes
- Query params:
workspace_idoptional
- Success:
200 OK
- Common errors:
400 Bad Requestfor invalidworkspace_id
- Description: Deletes an owned integration record.
- Auth: Yes
- Success:
204 No Content
- Common errors:
400 Bad Request404 Not Found
- Description: Returns provider configuration and connection status.
- Auth: Yes
- Query params:
workspace_idoptional
- Success:
200 OK
- Description: Starts Slack OAuth and returns the authorization URL.
- Auth: Yes
- Query params:
workspace_idrequired
- Success:
200 OK
- Common errors:
400 Bad Request503 Service Unavailablewhen Slack is not configured
- Description: Handles the Slack OAuth callback and stores the integration.
- Auth: No
- Query params:
coderequiredstaterequired
- Success:
200 OK
- Common errors:
400 Bad Request500 Internal Server Error503 Service Unavailable
- Description: Lists Slack channels for a connected integration.
- Auth: Yes
- Query params:
integration_idrequired
- Success:
200 OK
- Common errors:
400 Bad Request404 Not Found429 Too Many Requests
- Description: Starts GitHub OAuth and returns the authorization URL.
- Auth: Yes
- Success:
200 OK
- Common errors:
503 Service Unavailablewhen GitHub is not configured
- Description: Handles the GitHub OAuth callback and stores the integration.
- Auth: No
- Query params:
coderequiredstaterequired
- Success:
200 OK
- Common errors:
400 Bad Request401 Unauthorized500 Internal Server Error
- Description: Lists repositories available through the authenticated user's GitHub integration.
- Auth: Yes
- Success:
200 OK
- Description: Starts a GitHub sync job.
- Auth: Yes
- Success:
200 OK
{
"status": "sync_started"
}- Description: Disconnects the authenticated user's GitHub integration.
- Auth: Yes
- Success:
200 OK
- Description: Lists signals for the authenticated user.
- Auth: Yes
- Query params:
source_typeoptionalstatusoptional
- Success:
200 OK
- Description: Lists workspace-scoped signals with optional filters and pagination.
- Auth: Yes
- Query params:
source_typeoptionalstatusoptionallimitoptional, defaults to50, max100offsetoptional
- Success:
200 OK
{
"signals": [],
"total": 0
}- Common errors:
400 Bad Request
- Description: Returns a single signal for the authenticated user.
- Auth: Yes
- Success:
200 OK
- Common errors:
400 Bad Request404 Not Found
- Description: Marks a signal as read for the authenticated user.
- Auth: Yes
- Success:
204 No Content
- Common errors:
400 Bad Request404 Not Found
- Description: Marks a signal as archived for the authenticated user.
- Auth: Yes
- Success:
204 No Content
- Common errors:
400 Bad Request404 Not Found
- Description: Receives GitHub webhook payloads.
- Auth: No
- Headers:
X-GitHub-Eventrequired
- Success:
200 OK
- Common errors:
400 Bad Request405 Method Not Allowed