Step 2: Add Authentication and Permissions

This step adds authentication capabilities to your project management application. You'll configure user profile management linked to your User type and create machine users for different roles, enabling secure access control and automated operations. You will also implement role-based permissions to control data access.

What This Step Does

In this step, you enhance your application by:

  1. Configuring an auth namespace called "main-auth"
  2. Linking user profiles to your TailorDB User type
  3. Creating machine users for user roles with predefined attributes
  4. Creating permission definitions for logged-in users

Configuration Files

To follow along, review the configuration files for this step here.

tailor.config.ts

This file now includes authentication configuration:

<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> { defineAuth</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> defineConfig } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;@tailor-platform/tailor-sdk&quot;</span><span style="color: var(--shiki-color-text)">;</span></span>
<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> { user } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;./src/db/user&quot;</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> (</span><span style="color: var(--shiki-token-keyword)">!</span><span style="color: var(--shiki-token-constant)">process</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">env</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">WORKSPACE_ID</span><span style="color: var(--shiki-color-text)">) {</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-keyword)">throw</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">new</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">Error</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&quot;WORKSPACE_ID environment variable is not set&quot;</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">default</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">defineConfig</span><span style="color: var(--shiki-color-text)">({</span></span>
<span><span style="color: var(--shiki-color-text)">  workspaceId</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">process</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">env</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">WORKSPACE_ID</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  name</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;project-management&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  db</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> { </span><span style="color: var(--shiki-token-string-expression)">&quot;main-db&quot;</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> { files</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">`./src/db/*.ts`</span><span style="color: var(--shiki-color-text)">] } }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  auth</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">defineAuth</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&quot;main-auth&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    userProfile</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      type</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> user</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      usernameField</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;email&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      attributes</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">        role</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    machineUsers</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">      manager</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">        attributes</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> { role</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;MANAGER&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      staff</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">        attributes</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> { role</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;STAFF&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  })</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">});</span></span>
<span></span>

The userProfile configuration links authentication to your database:

  • type: user: Connects the auth system to your TailorDB User type
  • usernameField: "email": Specifies that the email field should be used as the username for login
  • attributes: { role: true }: Exposes the role field from the User type to the authentication context

src/common/permission.ts

This file defines reusable permission rules:

<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">type</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  PermissionCondition</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  TailorTypeGqlPermission</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  TailorTypePermission</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">} </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;@tailor-platform/tailor-sdk&quot;</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">interface</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">User</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  role</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">string</span><span style="color: var(--shiki-color-text)">;</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">loggedIn</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)">  { user</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;_loggedIn&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-string-expression)">&quot;=&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">] </span><span style="color: var(--shiki-token-keyword)">as</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">satisfies</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">PermissionCondition</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)">// Any logged-in user can do anything.</span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">permissionLoggedIn</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">  create</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [loggedIn]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  read</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [loggedIn]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  update</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [loggedIn]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  delete</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [loggedIn]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">} </span><span style="color: var(--shiki-token-keyword)">as</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">satisfies</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">TailorTypePermission</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)">// Any logged-in user can perform all GraphQL operation.</span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">gqlPermissionLoggedIn</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)">  {</span></span>
<span><span style="color: var(--shiki-color-text)">    conditions</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> [loggedIn]</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    actions</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;all&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    permit</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">] </span><span style="color: var(--shiki-token-keyword)">as</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">satisfies</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">TailorTypeGqlPermission</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>

This file defines two levels of permissions:

  1. Record-level permissions (TailorTypePermission): Enforced at the database layer

    • Controls create, read, update, delete operations on individual records
    • Evaluated before any database query executes
  2. GraphQL operation permissions (TailorTypeGqlPermission): Enforced at the API layer

    • Controls which GraphQL operations users can execute
    • Evaluated before the GraphQL resolver runs

Both layers must pass for an operation to succeed. This provides defense-in-depth security.

src/db/project.ts

The Project type now includes status, dates, and permissions:

<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> { db } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;@tailor-platform/tailor-sdk&quot;</span><span style="color: var(--shiki-color-text)">;</span></span>
<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> { gqlPermissionManager</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> permissionManager } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;../common/permission&quot;</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-keyword)">export</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">project</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> db</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-function)">.type</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&quot;Project&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)">    name</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">db</span><span style="color: var(--shiki-token-function)">.string</span><span style="color: var(--shiki-color-text)">()</span><span style="color: var(--shiki-token-function)">.description</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&quot;Name of the Project&quot;</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    description</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> db</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">.string</span><span style="color: var(--shiki-color-text)">({ optional</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-color-text)"> })</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">.description</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&quot;Description of the project&quot;</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    status</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">db</span><span style="color: var(--shiki-token-function)">.enum</span><span style="color: var(--shiki-color-text)">(</span></span>
<span><span style="color: var(--shiki-color-text)">      { value</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;PLANNING&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> description</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;Planning status&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      { value</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;IN_PROGRESS&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> description</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;In Progress status&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      { value</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;ON_HOLD&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> description</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;On hold status&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      { value</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;COMPLETED&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> description</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;Completed status&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      { value</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;CANCELED&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> description</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;Canceled status&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">      { value</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;CLOSED&quot;</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> description</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">&quot;Closed status&quot;</span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    )</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    startDate</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> db</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">.date</span><span style="color: var(--shiki-color-text)">({ optional</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-color-text)"> })</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">.description</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&quot;Start date of the project&quot;</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    endDate</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> db</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">.date</span><span style="color: var(--shiki-color-text)">({ optional</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-color-text)"> })</span></span>
<span><span style="color: var(--shiki-color-text)">      </span><span style="color: var(--shiki-token-function)">.description</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">&quot;End date of the project&quot;</span><span style="color: var(--shiki-color-text)">)</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">    </span><span style="color: var(--shiki-token-keyword)">...</span><span style="color: var(--shiki-token-constant)">db</span><span style="color: var(--shiki-token-function)">.</span><span style="color: var(--shiki-token-constant)">fields</span><span style="color: var(--shiki-token-function)">.timestamps</span><span style="color: var(--shiki-color-text)">()</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)">  })</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-function)">.permission</span><span style="color: var(--shiki-color-text)">(permissionManager)</span></span>
<span><span style="color: var(--shiki-color-text)">  </span><span style="color: var(--shiki-token-function)">.gqlPermission</span><span style="color: var(--shiki-color-text)">(gqlPermissionManager);</span></span>
<span></span>

Key additions:

  • .permission(): Applies record-level permissions
  • .gqlPermission(): Applies GraphQL operation permissions

Expected Outcome

After deploying this configuration with npm run deploy, you should see:

  1. An auth namespace "main-auth" created in your workspace
  2. User profile configuration linked to the User type

You can verify the setup by:

  • Viewing the auth configuration in the Tailor Console
  • Testing API calls with machine users

What's Next

In the next step, you'll add permissions to control who can access and modify data based on their role. The role attribute you've exposed in this step will be used in permission rules to enforce access control.

Next Step

Continue to Step 3: Add Pipeline and Permissions.