Skip to content

Security and Data

ForgeOS expresses auth, policies, secrets, tenant scope, and database rules as generated contracts — not ad-hoc checks scattered through handlers.

Auth modes

Configure via generated authConfig.json and environment variables:

Mode Use Production
dev-headers Local dev (x-forge-user-id, x-forge-tenant-id, x-forge-role) No
jwt Bearer JWT with configured issuer/audience Yes
oidc OIDC discovery + JWKS via jose Yes
disabled Testing only No

Environment variables (names vary by app):

FORGE_AUTH_MODE=jwt
FORGE_AUTH_ISSUER=
FORGE_AUTH_AUDIENCE=
FORGE_AUTH_JWKS_URI=
FORGE_AUTH_ALGORITHMS=

JWT/OIDC claims map to Forge auth context:

Claim Typical JWT field
User ID sub
Tenant ID tenant_id
Role role / roles

Check auth configuration:

forge auth check --json
forge inspect auth --json

Production deployments must not rely on dev-headers. Forge emits guardrails when dev auth is enabled in production-like modes.

Policies (RBAC)

Policies are declared in src/policies.ts and referenced from runtime entries:

import { can, command } from "forge/server";

export const createTicket = command({
  auth: can("tickets.create"),
  handler: async (ctx, args) => { /* ... */ },
});

Simulate policy decisions:

forge policy simulate tickets.create --role member --json
forge inspect policies --json

When a user receives 403:

forge telemetry inspect <traceId>
forge policy simulate <policyName> --role <role> --json

See Troubleshooting — Policy and auth errors.

Tenant isolation

Tenant-scoped tables declare tenantId in src/forge/schema.ts. Generated metadata includes:

  • tenantScope.json — which tables are tenant-bound
  • permissionMatrix.json — role × policy matrix
  • rlsPolicies.sql — Postgres RLS when enabled

Commands and queries must respect tenant scope. Agent tools and auto-tools inherit the same auth/tenant context as runtime handlers.

Secrets and environment

Recipes and integrations register secret names — never values — in secretRegistry.json:

forge inspect secrets --json
forge secrets list --json
forge env check --json

At runtime in actions, workflows, and endpoints:

const key = ctx.secrets.get("STRIPE_SECRET_KEY");

Forbidden in commands, queries, liveQueries, and client code:

process.env.STRIPE_SECRET_KEY; // FORGE_SECRET_LEAK / guard violation

Configure values in .env (gitignored). List expected names:

forge env list --json

Database

Forge compiles schema to SQL DDL and migration plans:

forge db diff --json
forge db migrate --db pglite
forge db status --json
forge db reset --db pglite   # local dev only

Local dev often uses PGlite; production uses Postgres with optional RLS enforcement.

Row Level Security (RLS)

For Postgres deployments, Forge can compile tenant rules to database-enforced RLS:

forge rls check --json
forge rls test --db postgres --json
forge rls mutate-test --json

Generated artifacts:

  • src/forge/_generated/rlsPolicies.sql
  • src/forge/_generated/dbSecurityManifest.json

RLS complements application-level policies — it blocks cross-tenant reads even if application code regresses.

PGlite local dev may not treat RLS as production-authoritative. Run forge rls check before shipping Postgres deployments. Run forge rls mutate-test --json to verify that generated RLS artifacts fail closed when FORCE RLS, policies, predicates, or runtime roles are weakened.

Data workflow for new tables

# 1. Edit schema
# src/forge/schema.ts — include tenantId when tenant-scoped

forge generate
forge db diff
forge db migrate --db pglite
forge rls check --json
forge verify --standard

Or scaffold with:

forge make resource tickets --fields title:text --dry-run --json

See Authoring.

Security checklist

Before production:

forge check --json
forge auth check --json
forge secrets check --json
forge rls check --json
forge rls mutate-test --json
forge verify --strict

Ensure:

  • Production auth mode is jwt or oidc
  • No process.env in app handlers
  • No network SDKs in commands/queries/liveQueries
  • Tenant-scoped tables include tenantId
  • Webhook endpoints verify signatures (see Payments)