# Team Workspace

Picture the app this track is modeled on: a production context-accumulator chat application built on NetScript. An operations team lives in it during an ERP cutover — projects and channels full of live incident context, diagnostics, and half-finished conclusions about a production system that is misbehaving *right now*. Underneath all of that sits an unglamorous layer that decides everything: **who is on the team, where their data lives, and which routes they may touch**. Get it wrong in one direction and an off-boarded contractor can still read incident channels; get it wrong in the other and the engineer you just paged is locked out while production burns.

The differentiator this track proves is that **the identity layer is NetScript's to ship, not yours to rebuild**: a pluggable auth backend, a normalized session, and a typed `.withAuthn()` / `.withAuthz()` route seam — in place of the bespoke sign-in flow and hand-rolled route middleware most stacks reimplement, and re-secure, once per app.

That layer is what you build here, from an empty folder to a running, session-protected app under Aspire: you scaffold a workspace (Postgres by default, swappable to `mysql`, `mssql`, or `sqlite` via `--db`), sign users in through a pluggable auth backend, give team records their own isolated database, provision new members with a background job that never blocks the caller, and gate your service routes with the real `.withAuthz()` seam. It is one continuous app — your `my-workspace/` grows with every chapter.

1. [1 · Scaffold](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/01-scaffold/)
2. [2 · Auth](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/02-auth/)
3. [3 · Workspace data](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/03-workspace-data/)
4. [4 · Provision job](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/04-provision-job/)
5. [5 · Route authz](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/05-route-authz/)
6. [6 · Deploy](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/06-deploy/)

## What you will build

By the end of this track you will have a NetScript workspace that signs a real user in through an OAuth/OIDC provider, mints a session cookie, stores team records in their own isolated Postgres (the default; or `mysql` / `mssql` / `sqlite` via `--db`), provisions a new member off the request path with a background job, and rejects unauthenticated requests to its guarded routes with a `401` — all running locally under one Aspire dashboard. The central idea: **authentication in NetScript is a pluggable backend, a session, and a route-authz seam — not a bespoke rewrite you carry yourself.**

> What NetScript ships — and what stays your code
>
> NetScript ships
>
> pluggable auth backends
>
> (an
>
> auth-api
>
> service with a single active backend chosen by an env var), a normalized
>
> session
>
> , and a provider-agnostic
>
> route-authz seam
>
> (
>
> .withAuthn()
>
> /
>
> .withAuthz()
>
> ). It does
>
> not
>
> ship first-class organizations, tenants, or RBAC roles. The "team workspace" app framing is real, but the data model is single-tenant: when this track touches multi-tenant org scoping, it does so as a clearly-marked
>
> app-level extension
>
> (you add your own
>
> orgId
>
> column and filter in your own queries), never as a framework-managed primitive. Read those asides as "here is how you would extend it," not "NetScript does this for you."

> Where this track's patterns come from
>
> The data shape is borrowed from a real app: a production chat application built on NetScript splits an
>
> org-catalog
>
> datasource (who exists, which projects and channels there are) from the data each channel accumulates — the dual-database pattern you build in chapter 3, and the same
>
> workers
>
> -plugin background jobs you use in chapter 4. The
>
> auth chapters are the exception
>
> : they are grounded in the framework's own packages and its
>
> builder-auth
>
> test suite (the 401/403/200 pattern in chapter 5), because that is where the authentication seam is actually defined and proven.

## The arc: auth → session → authz

Three ideas carry the whole track, and each chapter adds exactly one:

- **Auth** — a *backend* turns a sign-in into an identity. You pick one of three backends (`kv-oauth`, `workos`, `better-auth`) with an environment variable; the contract is identical across all three.
- **Session** — a successful sign-in mints a normalized `AuthSession` and sets a session cookie. Every later request resolves the current session from that cookie.
- **Authz** — a service gates its own routes with `.withAuthn()` (resolve a `Principal`) and `.withAuthz()` (decide from it). This is route-level authorization, scoped to route-level — not org/role RBAC.

## Who this is for

You should be comfortable with the basics from the [core tutorial ladder](https://rickylabs.github.io/netscript/tutorials/) — scaffolding a workspace, the contract → service flow, and bringing up Aspire. This track does not re-teach those; it assumes you can scaffold and boot, then layers authentication on top. If `netscript init` and `aspire start` are new to you, walk the [Quickstart](https://rickylabs.github.io/netscript/quickstart/) first.

## The six chapters

[1 · Scaffold  Create `my-workspace/` with an example service and Postgres, then boot it under Aspire. The base your authenticated app grows from.](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/01-scaffold/)

[2 · Auth  Add the `auth` plugin, choose the interactive `kv-oauth` backend, run the `auth.prisma` migration, and verify a live session on the `auth-api` service at :8094.](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/02-auth/)

[3 · Workspace data  Give the workspace its own isolated database with `netscript db add` and a per-datasource schema. The app-level `orgId` column appears here as an Extend aside.](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/03-workspace-data/)

[4 · Provision job  Move member provisioning off the request path: author a `defineJobHandler` job that creates a workspace membership, and trigger it over the Workers API.](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/04-provision-job/)

[5 · Route authz  Protect your service routes with the real, tested `.withAuthn()` / `.withAuthz()` seam — an authenticated request succeeds, an unauthenticated one gets a 401.](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/05-route-authz/)

[6 · Deploy  Run the whole workspace locally under Aspire — including the :8094 auth service — and read it from one dashboard. Shows the local-vs-production topology clearly.](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/06-deploy/)

## What you built

A clear map of the track: the team layer that a real operations tool stands on — a pluggable auth backend, a session, isolated team data, off-path provisioning, and a route-authz seam that fails closed. Single-tenant by design, with org scoping as an explicit app-level extension. Start at chapter 1 and keep the same `my-workspace/` through to deploy.

[Tutorials](https://rickylabs.github.io/netscript/netscript/tutorials/) [1 · Scaffold](https://rickylabs.github.io/netscript/netscript/tutorials/workspace/01-scaffold/)

After this track, keep building in **Build › [Identity & Access](https://rickylabs.github.io/netscript/identity-access/)** — the guides and recipes there pick up where these chapters stop.
