> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chardb.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Ownership

> Bind tables to organization, user, or organization-and-user ownership.

Every Worker chooses one ownership mode in `chardb()`. Organization mode accepts tables from `forOrg(auth)` and `forOrgUser(auth)`. User mode accepts only `forUser(auth)`. CharDB rejects a schema that mixes the two modes.

## Own rows with an organization

This is the exact schema generated by the packaged initializer.

```ts src/schema.ts theme={null}
import { file } from "@chardb/core/files";
import { integer, text } from "drizzle-orm/sqlite-core";
import { forOrg } from "@chardb/core/server";
import { auth } from "./auth.ts";

const { cdbTable } = forOrg(auth);

export const messages = cdbTable(
  "messages",
  {
    id: text("id").primaryKey(),
    authorId: text("author_id")
      .notNull()
      .references(() => auth.user.id, { onDelete: "cascade" }),
    body: text("body").notNull(),
    attachment: file("attachment", { maxSize: 5 * 1_024 * 1_024, contentTypes: ["image/jpeg", "image/png"] }),
    createdAt: integer("created_at").notNull(),
  },
  {
    selfBy: "authorId",
    roles: {
      owner: "*",
      admin: "*",
      member: { read: "*", create: ["id", "body", "attachment", "createdAt"] },
      self: { read: "*", update: ["body", "attachment"], delete: true },
    },
  },
);
```

`forOrg(auth)` adds `organizationId` as a non-null Drizzle reference to `auth.organization.id`. CharDB uses that schema reference to derive ownership; shard migrations do not install a physical foreign key to the Catalog-owned auth table. The column selects the partition, and the policy decides which current members may read or write each column.

Query definitions keep `organizationId` because the router needs one exact partition. The configured `@chardb/react` client reads the active organization from Better Auth and adds it to query and mutation arguments. CharDB still verifies the JWT and current membership before using it.

CharDB fills `organizationId` and `authorId` from verified authority during inserts. Mutation handlers omit both values. Defining `organizationId` yourself is a type error and a runtime error.

## Own rows with a user

Choose `ownership: "user"` for a Worker whose rows follow the signed-in user rather than an active organization.

```ts src/preference-schema.ts theme={null}
import { text } from "drizzle-orm/sqlite-core";
import { forUser } from "@chardb/core/server";
import { auth } from "./auth.ts";

const { cdbTable } = forUser(auth);

export const preferences = cdbTable("preferences", {
  id: text("id").primaryKey(),
  value: text("value").notNull(),
});
```

`forUser(auth)` adds `userId`, partitions by it, and fills it from the verified JWT subject. The configured React client adds that owner to client operations, and the server rejects any value that does not match the verified subject. The implicit `self` policy grants the owning user access.

## Own a row with an organization and user

In an organization-owned Worker, use `forOrgUser(auth)` for rows owned by one member inside the organization.

```ts src/draft-schema.ts theme={null}
import { text } from "drizzle-orm/sqlite-core";
import { forOrgUser } from "@chardb/core/server";
import { auth } from "./auth.ts";

const { cdbTable } = forOrgUser(auth);

export const drafts = cdbTable(
  "drafts",
  {
    id: text("id").primaryKey(),
    title: text("title").notNull(),
  },
  {
    roles: {
      admin: { read: "*" },
      self: { create: ["id", "title"], read: "*", update: ["title"], delete: true },
    },
  },
);
```

CharDB adds, fills, and checks both foreign keys. Organization admins can read every draft under this policy. Other members see only their own.

Next, make the message list update in [Live queries](/live-queries).
