Skip to content

ReaderAccountService

reference
1 min readUpdated

Kind: Service

Source: atloria-monorepo/apps/api/src/reader-account/reader-account.service.ts

C3 reader accounts — the reader-facing side (whoami / usage / delete).

Identity comes EXCLUSIVELY from the verified docs-reader token (claims.sub = ReaderAccount.id) — never from params or body. This service can never satisfy an org-member route: it has no notion of User/organization membership at all (separate plane by construction).

ReaderAccountService manages reader-facing account operations for C3, including identity lookup, usage retrieval, and account deletion. It derives the reader identity exclusively from the verified docs-reader token (claims.sub), ensuring these endpoints cannot be used as organization-member routes or accept identity from request params or bodies.

Methods

MethodSignatureReturnsDescription
requireAccount`requireAccount(claims: ReaderClaimsnullundefined)`
meme(accountId: string, projectId: string)`Promise<{ readerId: string; email: string; signedUpAt: Datenull }>`
usageusage(accountId: string, projectId: string)Promise<ReaderUsage>TTFC checklist + daily bars + the reader's own request log.
deleteAccountdeleteAccount(accountId: string)Promise<{ deleted: true }>Day-one right-to-erasure: deletes the GLOBAL reader account (profiles + keys cascade via FK) and ANONYMIZES the call log — rows keep their status/path/latenc…

Dependencies

  • PrismaService

Where it refuses work

  • ReaderAccountService stops the work with UnauthorizedException when !accountId || typeof accountId !== 'string'.
  • ReaderAccountService stops the work with UnauthorizedException when !account.

Diagram

mermaid
sequenceDiagram
  participant Client as Reader Client
  participant Guard as Docs Reader Auth Guard
  participant Service as ReaderAccountService
  participant DB as Database

  Client->>Guard: Request /reader-account/me|usage|delete
  Guard->>Guard: Verify docs-reader token
  Guard->>Service: Inject claims.sub as ReaderAccount.id

  Service->>Service: requireAccount()
  alt me()
    Service->>DB: Find ReaderAccount by id
    DB-->>Service: Account details
    Service-->>Client: readerId, email, signedUpAt
  else usage()
    Service->>DB: Load reader usage data
    DB-->>Service: ReaderUsage
    Service-->>Client: Usage summary
  else deleteAccount()
    Service->>DB: Delete ReaderAccount and related data
    DB-->>Service: Deletion complete
    Service-->>Client: { deleted: true }
  end

Usage

ts
import { Controller, Delete, Get } from '@nestjs/common';
import { ReaderAccountService } from './reader-account.service';

@Controller('reader-account')
export class ReaderAccountController {
  constructor(
    private readonly readerAccountService: ReaderAccountService,
  ) {}

  @Get('me')
  async me() {
    // Identity is resolved internally from verified docs-reader claims.
    return this.readerAccountService.me();
  }

  @Get('usage')
  async usage() {
    return this.readerAccountService.usage();
  }

  @Delete()
  async deleteAccount() {
    return this.readerAccountService.deleteAccount();
  }
}

AI Coding Instructions

  • Always resolve the active reader through verified docs-reader token claims; claims.sub must map directly to ReaderAccount.id.
  • Never accept a reader/account ID from route parameters, query parameters, or request bodies for these operations.
  • Use requireAccount() before performing reader-scoped work so unauthenticated or invalid reader contexts fail consistently.
  • Keep this service isolated from User, organization, and organization-membership logic; it must not satisfy org-member authorization requirements.
  • When adding account-related operations, preserve the reader-facing response shape and avoid exposing unrelated internal account fields.

Relationships

  • DEPENDS_ON → PrismaService

Referenced By

  • ReaderAccountController (DEPENDS_ON)
  • ReaderAccountModule (MODULE_PROVIDES)
  • ReaderAccountModule (MODULE_EXPORTS)

Was this page helpful?

Download as PDF