# filters (/docs/reference/api/filters)

> Data filtering: which resources of one type may a principal perform one action on, as a filter the application applies in its own database query instead of fet…



Data filtering: which resources of one type may a principal perform one action on, as a filter the application applies
in its own database query instead of fetching every row and calling `authorize` on each. The server partially evaluates
the same grants, deny statements, boundaries, relationship tuples, session limits and delegations a decision uses,
and returns a **plan**: `always`, `never`, or `conditional` with a filter over the resource's `id` and attributes. A
resource passes the filter exactly when `authorize` would allow it. Compile the filter with `filterToSql`,
`filterToPrisma`, `filterToMongo` or `filterMatches` from `@better-iam/core`. The in-process form is
`iam.planResources`. The repository guide is `docs/data-filtering.md`.

## Plans and filters [#plans-and-filters]

A `conditional` plan's `filter` is a tree of `and`, `or`, `not`, `exists`, `type`, `equals`, `compare`, `like`
(globs with `*`, `?` and `\` escapes), `date`, `ip` and `contains` nodes. Fields are `id` and the attribute names that
`resource.{name}` conditions use: the attributes `resolveResource` returns for application resources, the registry's
for managed ones. Resource patterns become conditions on `id` (`document/public-*` is `id like "public-*"`),
`resource.relations` conditions become the ids the principal holds the relation on, and conditions on the principal,
the request and the tenant are decided when the plan is made. A missing attribute satisfies nothing but `not exists`,
and every compiler keeps that rule under negation.

| Method                | What it does                                                                                                                                                                                                                            | Access     |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| [`plan`](#plan)       | The caller's plan for `action` on resources of `type`.                                                                                                                                                                                  | Credential |
| [`planFor`](#planfor) | An administrator's preview of another identity's plan, without a session of theirs, as [`policies.simulate`](/docs/reference/api/policies#simulate) does for one decision. `assumeMfa` plans as if the identity had signed in with MFA. | Credential |

## plan [#plan]

The caller's plan for `action` on resources of `type`.

**HTTP:** `POST /api/iam/filters/plan` (requires a credential) · **Browser client:** `client.filters.plan()`

* **Permission:** None beyond a session of the tenant; a session of another tenant plans `never`.
* **Audited as:** Not audited: your query decides which rows come back, and `authorize` remains the check for one
  resource.
* **Errors:** `INVALID_INPUT` for an `iam:*` action, an internal type (`iam`, `role`, `saml`, ...), or a malformed
  type name.

An unknown action plans `never`. A root administrator's session plans `always`. A "view as" session gets only what the
administrator behind it could reach too. A delegated session whose delegation holds the action for the person's
confirmation plans `never` (use `authorize` for the resources confirmed just now).

```ts
const plan = await iam.api.filters.plan(credential, {
  tenantId,
  action: 'documents:read',
  type: 'document',
});
// plan.kind: 'always' | 'never' | 'conditional'
```

```ts title="Signature"
iam.api.filters.plan(
  credential: CredentialInput,
  input: { tenantId: string; action: string; type: string },
): Promise<ResourcePlanResult>
```

## planFor [#planfor]

An administrator's preview of another identity's plan, without a session of theirs, as [`policies.simulate`](/docs/reference/api/policies#simulate) does for one decision. `assumeMfa` plans as if the identity had signed in with MFA.

**HTTP:** `POST /api/iam/filters/planFor` (requires a credential) · **Browser client:** `client.filters.planFor()`

* **Permission:** `iam:policies:simulate` on the identity.
* **Audited as:** `iam:policies:simulate`, on the identity.
* **Errors:** `NOT_FOUND` for an identity outside the tenant or deleted; `INVALID_INPUT` as for `plan`.

```ts title="Signature"
iam.api.filters.planFor(
  credential: CredentialInput,
  input: {
    tenantId: string;
    identityId: string;
    action: string;
    type: string;
    assumeMfa?: boolean;
  },
): Promise<ResourcePlanResult>
```
