Files
Zachary Lowden 5e0949f1e9 docs(features): fix the six Core Systems Reference docs, which were never verified against code (#3666)
CLAUDE.md tells agents to consult docs/features/ before implementing a feature and
names eight docs. Six had not been touched since 0a59df66de (2026-01-15), the single
commit that created them. Auditing them against HEAD found that five were wrong on
the day they were written — this is not drift, the extraction was never checked.

Verified at 0a59df66de: the buzz enum already read Tip=0/Fee=25; src/event-engine-common
never existed; nsfwBrowsingLevelsArray already contained Blocked; the getCount procedure
has no commit that ever added it; the EntityMetric enums have never had Model/Download.

buzz-accounts (money severity):
- Documented Tip=1 and Fee=10. Actual: Tip=0 (1 is Dues), Fee=25 (10 is Training).
  Both fabricated numbers name a different real transaction type, so a hardcoded
  literal books the wrong type with no type error and no runtime failure. Replaced
  the restated enum with an import-and-reference-by-name instruction.
- The prize-pool example was impossible: createMultiAccountBuzzTransaction has
  fromAccountId min(1), so it cannot pay out of the central bank, and it omitted the
  required externalTransactionIdPrefix (also the refund key). Split into the real
  multi-account spend shape and the real createBuzzTransactionMany payout shape.
- Documented 3 of 9 account types; getUserBuzzAccount described as per-type balances
  when it returns a one-element array defaulted to yellow.

notifications (rewritten):
- Led with "the notification service runs in a separate repository". 927e31bfee
  (2026-07-01) folded it into apps/notifications + packages/civitai-notifications.
  The main schema now holds one notification model; the other three tables are in a
  separate DB the monolith cannot reach. notification-cache.ts was deleted. getCount
  never existed (counts are trpc.user.checkNotifications). Drawer/List had their
  responsibilities misattributed — the behavior is in NotificationsComposed.
  Rewritten around the three-way ownership table.

metrics-analytics (deleted, table repointed to entity-metrics.md):
- entityType:'Model'/metricType:'Download' are not in the enums (only Image, and
  seven metric types with no Download), so the tracking snippet never compiled.
- Query snippets read raw entityMetricEvents: zero files in src/ read that table;
  5 read _month and 6 read entityMetricDailyAgg_v2, with a regression test pinning it.
- Documented ClickHouse Buffer tables, a pattern with zero occurrences in the repo.
- entity-metrics.md already covers this ground accurately and is maintained.

image-resources:
- Both snippets non-compiling: fetch() returns a Record keyed by image id with
  resources nested one level down, not a flat array.
- Detection section inverted: detected=false means inherited from Post.modelVersionId,
  not hand-tagged. There is no per-image tagging mutation, so the doc sent readers
  looking for a UI that was never built.
- Added the Flipt-routed replica read (the DataPacket replica lacks the
  ImageResourceNew backfill), which is a live correctness trap for new queries.

nsfw-filtering + bitwise-flags:
- Both told you to import Flags from '~/event-engine-common/utils/nsfw-utils'. ~/ maps
  to src/ and that path has never existed; the real class is src/shared/utils/flags.ts
  (69 importers). The module they pointed at has zero importers.
- nsfwBrowsingLevelsFlag documented as "R, X, or XXX"; it includes Blocked (= 60).
- Raw-SQL column was nsfw_level; it is quoted camelCase "nsfwLevel".
- Added what the mask alone doesn't cover: onlySelectableLevels, unrated nsfwLevel=0,
  and the per-domain ceiling.

Bit values themselves were all correct and are kept, marked as mirroring enums.ts.
Line-number citations are dropped throughout — every one had rotted.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 20:36:21 -05:00

3.0 KiB

Bitwise Flag Utilities

Utilities for working with bitwise flags throughout the codebase.

Overview

The codebase uses bitwise flags extensively for:

  • NSFW levels and content filtering
  • Multi-select options stored efficiently (e.g. OnboardingSteps)

Feature flags are not bitwise — those are string-keyed and Flipt-backed, see src/server/services/feature-flags.service.ts.

Key Files

File Purpose
src/shared/utils/flags.ts Flags utility class
src/server/common/enums.ts NsfwLevel enum (the bit values)
src/shared/constants/browsingLevel.constants.ts Derived browsing-level flags + predicates

The Flags Class

import { Flags } from '~/shared/utils/flags';

Only the four methods below are covered here; flags.ts exports about a dozen more (toggleFlag, intersection, instanceToArray, diff, …). Read the file rather than assuming this list is complete.

Check if Flag is Set

// Check if a specific flag is set
Flags.hasFlag(instance, flag);

// Example: Check if user has PG13 enabled
const hasPG13 = Flags.hasFlag(userBrowsingLevel, NsfwLevel.PG13);

Check for Any Overlap

// Check if ANY bits overlap between two values
Flags.intersects(a, b);

// Example: Check if content is visible to user
const isVisible = Flags.intersects(contentLevel, userBrowsingLevel);
// Returns true if content's level matches any of user's allowed levels

Add a Flag

// Add a flag to an existing value
const newValue = Flags.addFlag(instance, flag);

// Example: Add R-rated content to user's preferences
const newLevel = Flags.addFlag(userBrowsingLevel, NsfwLevel.R);

Remove a Flag

// Remove a flag from an existing value
const newValue = Flags.removeFlag(instance, flag);

// Example: Remove XXX from user's preferences
const newLevel = Flags.removeFlag(userBrowsingLevel, NsfwLevel.XXX);

Common Patterns

Combining Multiple Flags

// Combine flags with bitwise OR
const multipleFlags = Flag.A | Flag.B | Flag.C;

// Example: Allow PG, PG13, and R content
const allowedLevels = NsfwLevel.PG | NsfwLevel.PG13 | NsfwLevel.R; // = 7

Checking Multiple Conditions

// Check if ALL flags are set (bitwise AND)
const hasAll = (value & requiredFlags) === requiredFlags;

// Check if ANY flags are set (intersects)
const hasAny = Flags.intersects(value, checkFlags);

Database Queries with Flags

The column is camelCase and must be quoted in raw SQL:

-- Check if content matches user's browsing level
WHERE (i."nsfwLevel" & :userBrowsingLevel) != 0

-- Check if specific flag is set
WHERE (flags & :specificFlag) = :specificFlag

TypeScript Enum Flags

// Define flags as powers of 2
enum MyFlags {
  None = 0,
  OptionA = 1,    // 0b0001
  OptionB = 2,    // 0b0010
  OptionC = 4,    // 0b0100
  OptionD = 8,    // 0b1000
  All = 15,       // 0b1111
}

See Also