Domain · Specifications

Arete — Technical Specifications

The table below summarizes the domain's key properties at a glance.

10sections22 minread

On this page

Personal development and life mastery domain. Named after the Ancient Greek concept of excellence, virtue, and living up to one's full potential.

This document specifies what is implemented in the Arete domain. Every schema, field, enum value, table, endpoint, and configuration key below is traceable to source code under libs/arete/*, apps/arete/*, or libs/contracts/src/arete/.

The document is organized in layers matching the implementation: domain overview and library inventory first, then the Zod validation schemas, then the database schema (both legacy and V1 contract tables), then the API surface, events, configuration, and integration points. A new engineer should read §1–2 for orientation, then jump to whichever section matches the area they are working on.


1. Domain Overview#

The table below summarizes the domain's key properties at a glance. The arete_ table prefix is consistent across all 61 database tables and all enum types.

Property Value
Domain name arete
Scope Personal development and life mastery
Library count 12 Nx libraries (libs/arete/*)
Application count 3 (apps/arete/api, apps/arete/web, apps/arete/mobile)
Database PostgreSQL via Drizzle ORM, arete_ table prefix
Language TypeScript (ESM)
Validation Zod
ORM Drizzle ORM (drizzle-orm ^0.38.0)
API framework Fastify (apps/arete/api)

libs/arete/database/ contains only prisma/schema.prisma and a generated prisma/generated/schema.sql. It has no package.json or project.json, so it is not an Nx library and is not counted above. The authoritative schema for the domain is the Drizzle ORM schema in @arete/core (src/db-schema.ts).


2. Library Inventory#

Twelve libraries carry a package.json and project.json. All are tagged ["scope:arete", "layer:domain", "type:lib"]. The source modules column lists every module file under src/ for each library.

Package Path Source modules
@arete/core libs/arete/core schemas, db-schema, db-seed
@arete/habits libs/arete/habits crud, habit-loop, four-laws, stacking, celebration, streaks, identity, keystone, analytics, reminders, recovery, friction, interventions
@arete/goals libs/arete/goals crud, hierarchy, smart, okr, woop, twelve-week-year, progress, analytics
@arete/journal libs/arete/journal crud, morning-pages, five-minute-journal, gratitude, thought-records, worry-journal, prompted-journal, reflection, analytics
@arete/time libs/arete/time eisenhower, gtd-inbox, gtd-review, big-rocks, time-blocking, pomodoro, deep-work, daily-planning, time-audit
@arete/vision libs/arete/vision vision-board, mission-statement, values-clarification, ikigai, golden-circle, legacy
@arete/balance libs/arete/balance wheel-of-life, wellness-dimensions, perma, mood-tracking, sleep-tracking, energy-management, life-satisfaction
@arete/seven-habits libs/arete/seven-habits be-proactive, begin-with-end, put-first-things-first, think-win-win, seek-to-understand, synergize, sharpen-the-saw, emotional-bank-account
@arete/affirmations libs/arete/affirmations management, ai-affirmations
@arete/gamification libs/arete/gamification points, badges, levels, leaderboards, accountability, contracts, challenges, rewards
@arete/ai-coach libs/arete/ai-coach coaching, recommendations, patterns, weekly-review, coaching-summary-card, continuity-card, cross-domain, nlp-analytics, notifications
@arete/api-client libs/arete/api-client client, generated/openapi

@arete/core carries runtime dependencies (@oshun/contracts, drizzle-orm, zod). The eight personal-development feature libraries, @arete/gamification, and @arete/ai-coach declare @arete/core as a peerDependency and carry no other runtime dependencies. @arete/api-client is a standalone generated client with no runtime dependency on @arete/core.

2.1 Applications#

App Path Stack
@arete/api apps/arete/api Fastify REST API; JWT auth, Drizzle/pg, Redis, Swagger, nodemailer
@arete/web apps/arete/web React + Vite, React Router, TanStack Query, Zustand, Tailwind, Recharts
@arete/mobile apps/arete/mobile React Native 0.73, React Navigation, TanStack Query, Zustand

@arete/api has the Nx tag set ["scope:arete", "type:app", "layer:service"].


3. Data Models — @arete/core/schemas.ts (56 Zod schemas)#

schemas.ts exports 56 *Schema constants. Each schema exports an inferred TypeScript type via z.infer. The numbered design comments in the file run 1–55 because two schemas (MaturityStageSchema enum and GratitudeItemSchema nested object) are sub-schemas of larger entities.

Shared field helpers (id, userId, datetime, dateOnly, timeOfDay) are defined once and reused. id/userId are z.string().uuid(); datetime is z.string().datetime() (ISO 8601); dateOnly matches YYYY-MM-DD; timeOfDay matches HH:mm (00:00–23:59).

The sub-sections below enumerate every schema in the file, grouped by the domain entity they represent.

3.1 Identity and Profile#

These schemas model the user and their defining personal context: who they are, what they value, what roles they inhabit, and where they stand on Covey's maturity continuum.

UserProfileSchema — user profile and preferences.

Field Type Notes
id uuid
email email, ≤255
name string, 1–255 display name
avatar url | null default null
timezone string, 1–100 IANA identifier, default UTC
locale string, 2–10 default en
createdAt datetime
updatedAt datetime
settings record<string, unknown> default {}

PersonalMissionSchema — mission statement with associated values.

Field Type Notes
id uuid
userId uuid
statement string, 10–5000 full mission statement
values ValueSchema[], ≥1 core values supporting mission
lastReviewed datetime | null
createdAt datetime

ValueSchemaid, userId, name (1–100), description (≤2000), priority (int 1–10, 1 = highest), category (1–100).

RoleSchemaid, userId, name (1–100), description (≤2000), goals (array of uuid, default []), isActive (boolean, default true).

MaturityStageSchema — enum: dependence, independence, interdependence (Covey's maturity continuum).

3.2 Goals#

These schemas cover the full goal model: the base goal entity shared across all five frameworks, plus the framework-specific extensions and sub-entities.

GoalSchema — base goal with hierarchical nesting.

Field Type Notes
id uuid
userId uuid
title string, 1–500
description string, ≤5000 default ''
type GoalTypeSchema
status GoalStatusSchema default not_started
startDate date (YYYY-MM-DD)
targetDate date (YYYY-MM-DD)
progress number 0–100 default 0
parentGoalId uuid | null default null

GoalTypeSchema — enum: annual, quarterly, monthly, weekly, daily.

GoalStatusSchema — enum: not_started, in_progress, completed, abandoned, paused.

SMARTGoalSchemaGoalSchema extended with specific, measurable, achievable, relevant, timeBound (each string, 1–2000). These are stored as additional columns on arete_goals rather than a separate table; see §5.1.

KeyResultSchemaid, okrId (uuid), description (1–1000), currentValue (number), targetValue (number), unit (1–50), score (number 0.0–1.0).

OKRSchemaid, userId, objective (1–1000), keyResults (KeyResultSchema[], 1–5), quarter (int 1–4), year (int 2000–2100), status (GoalStatusSchema, default not_started).

WOOPGoalSchemaid, userId, wish (1–1000), outcome (1–2000), obstacle (1–2000, the main internal obstacle), plan (1–2000, the if-then plan), status (GoalStatusSchema). Like SMART criteria, WOOP fields are columns on arete_goals rather than a separate table.

ImplementationIntentionSchemaid, userId, goalId (uuid), situation (1–1000, the "if" trigger), behavior (1–1000, the "then" action), strength (number 0–10).

3.3 Habits#

The habit schemas model the full cue-routine-reward lifecycle, completion records, streaks, and streak freezes. Note that the cue, routine, and reward sub-structures are validated individually before being stored as JSONB in the arete_habits table.

HabitSchema — a habit with cue-routine-reward loop and tracking stats.

Field Type Notes
id uuid
userId uuid
name string, 1–200
description string, ≤2000 default ''
category string, 1–100 e.g. health, productivity
frequency HabitFrequencySchema
cue HabitCueSchema
routine HabitRoutineSchema
reward HabitRewardSchema
isActive boolean default true
currentStreak int ≥0 default 0
bestStreak int ≥0 default 0
totalCompletions int ≥0 default 0
createdAt datetime

HabitFrequencySchema — enum: daily, weekly, specific_days, flexible, x_per_week.

HabitCueSchematype (enum: time, location, preceding_action, emotional_state), value (1–500), description (≤1000, default '').

HabitRoutineSchemasteps (array of 1–500-char strings, ≥1), starterStep (1–500, the tiny first step), durationMinutes (int 1–480), difficulty (int 1–5).

HabitRewardSchematype (enum: intrinsic, extrinsic), description (1–1000), points (int ≥0, default 0).

HabitStackSchemaid, userId, name (1–200), habits (array of uuid, ≥1, ordered), triggerCue (HabitCueSchema).

HabitCompletionSchemaid, habitId (uuid), userId, date (YYYY-MM-DD), completedAt (datetime | null), notes (≤2000, default ''), quality (int 1–5 | null), skipped (boolean, default false), skipReason (≤500 | null).

StreakSchemaid, habitId (uuid), userId, current (int ≥0), best (int ≥0), startDate (YYYY-MM-DD), lastCompletionDate (YYYY-MM-DD | null), forgivenessDaysUsed (int ≥0, default 0), forgivenessDaysAllowed (int ≥0, default 1).

StreakFreezeSchemaid, streakId (uuid), userId, date (YYYY-MM-DD), reason (≤500, default ''), wasAutomatic (boolean, default false).

3.4 Journal#

The journal schemas cover the core entry record, prompts, templates, CBT thought records, and gratitude entries. The JournalEntrySchema is the primary record; the specialized schemas below are separate entities linked to it.

JournalEntrySchema — a journal entry with mood tracking and tagging.

Field Type Notes
id uuid
userId uuid
title string, 1–500
content string, 1–50000 Markdown supported
mood int 1–5 | null 1 = very low, 5 = great
tags array of strings 1–50 default []
template string ≤100 | null template used for the entry
isPrivate boolean default true
wordCount int ≥0
createdAt datetime
updatedAt datetime

JournalPromptSchemaid, text (5–1000), category (enum: gratitude, reflection, growth, creativity, mindfulness), isSystem (boolean, default false).

JournalTemplateSchemaid, name (1–200), type (enum: five_minute, morning_pages, evening_reflection, weekly_review, monthly_review), prompts (array of 1–1000-char strings, ≥1), structure (record<string, unknown>, default {}).

ThoughtRecordSchema — a CBT thought record. The emotionIntensity and newEmotionIntensity fields bracket the before/after mood shift produced by completing the thought record exercise.

Field Type Notes
id uuid
userId uuid
situation string, 1–2000 the triggering situation
automaticThought string, 1–2000
emotion string, 1–100 the primary emotion
emotionIntensity int 0–100
evidenceFor string, ≤2000 default ''
evidenceAgainst string, ≤2000 default ''
balancedThought string, ≤2000 default ''
newEmotionIntensity int 0–100 | null intensity after reframing
createdAt datetime

GratitudeItemSchematext (1–500), category (1–100).

GratitudeEntrySchemaid, userId, items (GratitudeItemSchema[], 1–10), date (YYYY-MM-DD).

3.5 Vision#

The vision schemas model digital vision boards and the items placed on them. The VisionBoardCategorySchema enum restricts board categories to the ten life areas used throughout the domain; the item type field determines whether the board cell contains an image, text, or a linked goal.

VisionBoardCategorySchema — enum: career, health, relationships, finances, personal_growth, spirituality, adventure, creativity, family, education.

VisionBoardItemSchemaid, boardId (uuid), type (enum: image, text, goal_link), content (1–5000), position ({ x, y }, both ≥0), size ({ w, h }, both ≥1), goalId (uuid | null).

VisionBoardSchemaid, userId, name (1–200), description (≤2000), isActive (boolean, default true), items (VisionBoardItemSchema[], default []), createdAt.

3.6 Time Management#

The time management schemas span both higher-level planning (weekly plans with big rocks, daily plans with MIT trios) and execution-level records (Pomodoro sessions, deep work sessions, and individual tasks in the Eisenhower matrix).

TaskQuadrantSchema — enum: Q1_urgent_important, Q2_not_urgent_important, Q3_urgent_not_important, Q4_not_urgent_not_important (Eisenhower matrix).

TaskSchemaid, userId, title (1–500), description (≤5000), quadrant (TaskQuadrantSchema), priority (int 1–10, 1 = highest), dueDate (YYYY-MM-DD | null), estimatedMinutes (int 1–1440 | null), completedAt (datetime | null), isRecurring (boolean, default false), tags (array of strings 1–50, default []).

BigRockSchemaid, userId, weekStart (YYYY-MM-DD, Monday), title (1–500), description (≤2000), roleId (uuid | null), isCompleted (boolean, default false), priority (int 1–7).

TimeBlockSchemaid, userId, date (YYYY-MM-DD), startTime (HH:mm), endTime (HH:mm), title (1–500), category (enum: deep_work, admin, meeting, personal, health, learning), isFlexible (boolean, default false).

WeeklyPlanSchemaid, userId, weekStart (YYYY-MM-DD), bigRocks (BigRockSchema[], default []), roles (array of uuid), review (≤5000), sharpenTheSaw (≤2000, planned renewal activities).

DailyPlanSchemaid, userId, date (YYYY-MM-DD), bigThree (array of exactly 3 strings 1–500), timeBlocks (TimeBlockSchema[], default []), morningRoutine (≤2000), eveningReview (≤2000).

PomodoroSessionSchemaid, userId, taskId (uuid | null), startedAt (datetime), duration (int 1–120, default 25), breakDuration (int 0–60, default 5), completed (boolean, default false), distractions (int ≥0, default 0).

DeepWorkSessionSchemaid, userId, startedAt (datetime), endedAt (datetime | null), focusScore (int 0–100 | null), objective (1–1000), accomplishments (≤5000), distractions (int ≥0).

3.7 Seven Habits#

These schemas directly model Covey's constructs: the Circle of Influence/Concern classification, and the Emotional Bank Account with per-relationship transaction histories.

CircleOfInfluenceSchemaid, userId, item (1–1000), circle (enum: concern, influence), actionable (boolean, default false), notes (≤2000).

EmotionalTransactionSchemaid, accountId (uuid), type (enum: deposit, withdrawal), description (1–1000), amount (int 1–10, magnitude), category (enum: courtesy, kindness, honesty, commitment, apology, forgiveness), date (datetime).

EmotionalBankAccountSchemaid, userId, relationshipName (1–200), balance (int, may be negative), lastTransaction (datetime | null), transactions (EmotionalTransactionSchema[], default []).

3.8 Balance and Wellness#

The wellness schemas cover life balance assessment (Wheel of Life), renewal activity planning, and daily biometric check-ins (mood, sleep, energy). The WellnessDimensionSchema enum is the shared vocabulary for dimension types across all three assessment tools.

WellnessDimensionSchema — enum: physical, mental, emotional, spiritual, social, financial, career, family, fun_recreation, personal_growth, custom.

WheelOfLifeDimensionSchemadimensionType (WellnessDimensionSchema), customName (1–80, optional), customDescription (≤500, optional), rating (int 1–10), targetRating (int 1–10), notes (≤2000), actions (array of strings 1–500, default []). A .refine() enforces that customName is present whenever dimensionType is custom.

WheelOfLifeSchemaid, userId, dimensions (WheelOfLifeDimensionSchema[], ≥1), overallScore (number 0–10, computed), assessmentDate (YYYY-MM-DD), notes (≤5000).

RenewalActivitySchemaid, userId, dimension (WellnessDimensionSchema), activity (1–500), frequencyPerWeek (int 1–14), durationMinutes (int 1–480), notes (≤2000).

RenewalLogSchemaid, activityId (uuid), userId, date (YYYY-MM-DD), durationMinutes (int 1–480), quality (int 1–5), notes (≤2000).

MoodEntrySchemaid, userId, mood (int 1–5), energy (int 1–5), tags (array of strings 1–50, default []), notes (≤2000), date (datetime).

3.9 Affirmations#

AffirmationSchemaid, userId, text (1–1000), category (1–100), isActive (boolean, default true), frequency (enum: daily, weekly, on_demand, default daily), lastReviewedAt (datetime | null).

3.10 Gamification#

The gamification schemas model the three reward currencies (XP, coins, gems), the badge and leveling system, accountability partnerships, commitment contracts, and community challenges.

BadgeSchemaid, name (1–200), description (≤1000), category (1–100), icon (1–200), unlockCondition (1–1000, human-readable), points (int ≥0), tier (enum: bronze, silver, gold, platinum).

AchievementSchemaid, userId, badgeId (uuid), earnedAt (datetime | null), progress (number 0–100, default 0).

LevelSchemalevel (int 1–100), title (1–200), xpRequired (int ≥0), xpTotal (int ≥0, cumulative), perks (array of strings 1–500, default []).

PointsSchemaid, userId, amount (int ≥1), type (enum: xp, coins, gems), source (1–500), earnedAt (datetime).

AccountabilityPartnerSchemaid, userId, partnerUserId (uuid), status (enum: pending, active, ended, default pending), sharedGoals (array of uuid, default []), createdAt.

CommitmentContractSchemaid, userId, goalId (uuid), stake ({ description (1–1000), amount (≥0) }), referee (uuid | null), deadline (YYYY-MM-DD), status (enum: active, completed, failed, default active).

ChallengeSchemaid, title (1–500), description (1–5000), category (1–100), startDate (YYYY-MM-DD), endDate (YYYY-MM-DD), participantCount (int ≥0, default 0), rules (array of strings 1–1000, ≥1), prizes (array of strings 1–500, default []).


4. V1 Contract Schemas — @oshun/contracts/arete#

libs/contracts/src/arete/index.ts defines a second, newer schema family — the "V1" contracts. These describe the humane-streak / friction-aware coaching model: a more psychologically sensitive alternative to binary pass/fail habit tracking. The arete_v1_* Drizzle tables (see §5.3) and @arete/api-client types are typed against these contracts.

The V1 model introduces concepts not present in the legacy schemas: a declared difficulty rating for each habit, a humane streak policy that distinguishes between skip, decline, partial, and miss, friction signals from multiple Oshun domains, and an intervention dispatch system that suggests corrective actions when friction is detected.

4.1 Contract enums#

The V1 contracts define 21 enums. The table below lists each schema and its values. Note that some of these (e.g., FrictionSignalSourceSchema) name other Oshun domains as valid signal sources — this is the primary cross-domain coupling point in the Arete codebase.

Schema Values
CheckInStatusSchema done, partial, skip, decline, miss
HabitCadenceKindSchema (5 values; weekly / count-per-period / on-trigger among them)
DeclaredDifficultySchema tiny, easy, moderate, hard, stretch
GoalTimeframeSchema daily, weekly, monthly, quarterly, annual, multi-year, open-ended
GoalScopeSchema identity, health, learning, work, relationship, spiritual, financial, community, creative, custom
GoalStatusSchema (V1) not-started, active, paused, completed, abandoned
StreakTreatmentSchema engaged, grace, no-count
JournalEntryTypeSchema daily-reflection, weekly-review-note, cbt, gratitude, freeform, recovery, prompt-response
WeeklyReviewStatusSchema scheduled, started, completed, skipped
WeeklyReviewCadenceSchema sunday-evening, custom
PlanScopeSchema daily, weekly, recovery, goal-rescope, routine-adjustment
PlanStatusSchema draft, active, completed, superseded, archived
StreakVisualStateSchema steady, grace, drift, recovery, paused
MissedDayDispositionSchema within-grace, logged-miss, recovered, excused
FrictionSignalKindSchema time-of-day-mismatch, mood-incompatible-cadence, calendar-collision, cross-domain-cognitive-load, declared-sensitivity, location-friction, environment-unavailable, energy-drop, social-friction, streak-drift, over-scoped-plan
FrictionSignalSourceSchema check-in, journal, calendar, assistant, veritas, metis, tara, nyx, manual
FrictionSignalSeveritySchema low, medium, high
InterventionKindSchema notification-retiming, plan-rescope, alternative-habit, accountability-check-in, breathwork-insert, tara-ritual-surfacing, weekly-review-prompt, routine-substitution, goal-criteria-clarification
InterventionStatusSchema proposed, accepted, declined, applied, dismissed, expired
CoachingToneSchema invitational, direct, reflective, celebratory, recovery
RecoveryStageSchema invited, accepted, in-progress, completed, declined, expired

4.2 Contract entities#

The contract module exports thirteen entity schemas, each consumed by an arete_v1_* table: HabitSchema, RoutineSchema, GoalSchema, CheckInSchema, MissedDaySchema, JournalEntrySchema, WeeklyReviewSchema, PlanSchema, StreakRecordSchema, RecoveryRecordSchema, FrictionSignalSchema, InterventionSchema, CoachingSummarySchema. Supporting nested schemas include DeclaredCadenceSchema, HumaneStreakPolicySchema, RoutineStepSchema, GoalCompletionSchema, WeeklyReviewSectionSchema, PlanCommitmentSchema, StreakEventSchema, MoodSnapshotSchema, AreteMetricSchema, and AreteReferenceSchema.

Notable validation: DeclaredCadenceSchema uses .superRefine() to require daysOfWeek for a weekly cadence, targetCount + period for count-per-period, and triggerRef for on-trigger. HumaneStreakPolicySchema carries skipPreservesStreak, declinePreservesStreak, missGraceCadences (0–30), recoveryPromptAfterMisses (1–30), and visualLanguage (no-shame or neutral). The contract module also exports CHECK_IN_STREAK_TREATMENT, a Record<CheckInStatus, StreakTreatment> mapping each check-in status to its streak treatment.


5. Database Schema — @arete/core/db-schema.ts#

db-schema.ts exports Drizzle ORM table definitions, relations, enums, and raw SQL strings. ALL_ARETE_TABLES enumerates 61 tables; ALL_ARETE_ENUMS enumerates 39 pgEnum definitions (coachMessageRoleEnum is a 40th enum, defined inline and used by arete_coach_messages but not added to that array). All tables use the arete_ name prefix.

5.1 Legacy table groups#

The 48 legacy tables are organized into eleven functional groups. A few structural decisions are worth noting before reading the full list:

  • SMART and WOOP are columns, not tables. arete_goals carries smart_specific, smart_measurable, smart_achievable, smart_relevant, smart_time_bound, and woop_wish, woop_outcome, woop_obstacle, woop_plan directly. There are no separate arete_smart_goals or arete_woop_goals tables.
  • Goal hierarchy is modelled twice: a self-referential parent_goal_id on arete_goals, plus an explicit arete_goal_hierarchy join table with a unique (parent_goal_id, child_goal_id) index.
  • Credentials are separated from arete_users: arete_user_credentials holds the bcrypt password_hash so the profile table can be SELECT *'d safely. arete_password_reset_tokens holds single-use, time-bounded reset tokens.
  • Habit cue / routine / reward are stored as JSONB columns on arete_habits, not separate tables.
  • Mood, sleep, energy are separate tables (arete_mood_entries, arete_sleep_entries, arete_energy_entries), each with a sequence column so multiple same-day entries are ordered.
  • arete_habit_completions carries both the legacy fields and V1 check-in fields: status (arete_v1_check_in_status), engagement_percent, status_reason, streak_treatment (arete_v1_streak_treatment).
  • arete_partner_invitations records outgoing partnership invites by email (a partner need not have an existing account).
Group Tables
Identity arete_users, arete_user_credentials, arete_password_reset_tokens, arete_personal_missions, arete_values, arete_roles
Goals arete_goals, arete_goal_hierarchy, arete_okrs, arete_key_results
Habits arete_habits, arete_habit_completions, arete_habit_stacks, arete_streaks, arete_streak_freezes
Journal arete_journal_entries, arete_journal_prompts, arete_thought_records, arete_gratitude_entries
Vision arete_vision_boards, arete_vision_board_items
Time arete_tasks, arete_weekly_plans, arete_daily_plans, arete_time_blocks, arete_pomodoro_sessions, arete_deep_work_sessions
Seven Habits arete_circle_items, arete_relationships, arete_emotional_transactions
Balance arete_wheel_of_life_assessments, arete_wellness_logs, arete_renewal_activities, arete_renewal_logs, arete_mood_entries, arete_sleep_entries, arete_energy_entries
Affirmations arete_affirmations
Gamification arete_achievements, arete_badges, arete_user_levels, arete_points_transactions, arete_accountability_partnerships, arete_partner_invitations, arete_commitment_contracts, arete_challenges, arete_challenge_participants
Coaching arete_coach_conversations, arete_coach_messages, arete_coach_feedback

5.2 Legacy enums (subset)#

The following PostgreSQL enum types are defined in ALL_ARETE_ENUMS, all prefixed arete_ in the database:

maturity_stage, goal_type, goal_status, habit_frequency, journal_prompt_category, vision_board_item_type, task_quadrant, time_block_category, circle, emotional_transaction_type, emotional_transaction_category, wellness_dimension, affirmation_frequency, badge_tier, points_type, partnership_status, contract_status, challenge_participant_status, coach_message_role.

5.3 V1 contract-backed tables#

Thirteen arete_v1_* tables store the V1 contract entities. Their column lists are exported as ARETE_CONTRACT_RECORD_COLUMNS and the table objects as ARETE_CONTRACT_RECORD_TABLES (keyed Habit, Goal, Routine, CheckIn, Journal, WeeklyReview, Plan, CoachingSummary, Streak, MissedDay, Friction, Intervention, Recovery).

Table Stores
arete_v1_habits declared intent, difficulty, cadence, humane streak policy
arete_v1_goals timeframe, scope, measurable criteria, sub-goals, completion
arete_v1_routines declared cadence, time-of-day window, steps, substitution rules
arete_v1_check_ins status, engagement %, reflection, mood/energy, friction notes
arete_v1_journal_entries entry type, body markdown, linked habits/goals/check-ins
arete_v1_weekly_reviews sections, inputs, plan adjustments, next-practice recommendations
arete_v1_plans scope, status, commitments, linked entities, recovery linkage
arete_v1_coaching_summaries tone, celebrated wins, observed patterns, suggested adjustments
arete_v1_streak_records engagement counts, grace window, visual state, humane policy
arete_v1_missed_days disposition, grace expiry, friction-signal links, recovery link
arete_v1_friction_signals kind, source, severity, evidence refs, suggested interventions
arete_v1_interventions kind, status, triggering signals, target, recommendation
arete_v1_recovery_records stage, target, trigger, invitation, linked plan/interventions

The V1 enums (arete_v1_*, 20 enum types) mirror the contract enums in §4.1 and are listed in §4.1's value table.

5.4 Relations#

ALL_ARETE_RELATIONS exports Drizzle relations() definitions covering 55 tables. areteUsers is the hub: it declares many/one relations to missions, values, roles, goals, OKRs, habits, completions, streaks, journal entries, vision boards, tasks, plans, wellness logs, mood/sleep/energy entries, affirmations, achievements, the user level, points transactions, partnerships (both directions), commitment contracts (owner and referee), challenge participations, coach conversations/feedback, and all thirteen V1 record types. Foreign keys use onDelete: 'cascade' for owned data and onDelete: 'set null' for soft references (e.g. arete_vision_board_items.goal_id, arete_pomodoro_sessions.task_id, arete_commitment_contracts.referee).

5.5 Database automation (raw SQL exports)#

Three SQL blocks are exported as strings from db-schema.ts and are intended to be applied via migration. They encode the streak trigger, aggregation functions, and full-text search indexes respectively.

STREAK_CALCULATION_TRIGGER_SQL — defines the arete_update_streak_on_completion() PL/pgSQL function and the arete_streak_update_trigger (AFTER INSERT ON arete_habit_completions, FOR EACH ROW). The function logic proceeds as follows:

  1. Skip rows where skipped = true — a recorded skip does not affect the streak.
  2. Create a streak row for the habit if none exists yet.
  3. Compute the day gap between the current insertion date and last_completion_date.
  4. If the gap is 1 day (consecutive), increment current by 1.
  5. If the gap is within the forgiveness window, consume a forgiveness day and increment.
  6. If the gap exceeds the forgiveness window, reset current to 1.
  7. Update best if current now exceeds it.
  8. Write the new values back to both arete_streaks and the denormalized fields on arete_habits (current_streak, best_streak, total_completions).

STATISTICS_AGGREGATION_SQL — defines nine STABLE PL/pgSQL functions. Each function is optimized for the dashboard and coach aggregation queries:

Function Returns
arete_total_completions(user, start?, end?) count of non-skipped habit completions
arete_average_mood(user, start?, end?) average mood from arete_mood_entries
arete_average_energy(user, start?, end?) average energy from arete_mood_entries
arete_goal_completion_rate(user) completed / total goals as a 0–100 percentage
arete_total_xp(user) sum of xp-type points transactions
arete_habit_completion_rate(habit, days = 30) completions over N days as a 0–100 percentage
arete_journal_stats(user) OUT params: entry count, avg word count, total words
arete_wheel_of_life_trend(user) OUT params: current score, previous score, trend
arete_deep_work_hours(user, start?, end?) total deep-work hours (sum of session durations)

JOURNAL_FULLTEXT_INDEX_SQL — creates two GIN indexes, arete_journal_entries_content_fts_idx and arete_journal_entries_title_fts_idx, both over to_tsvector('english', …).

5.6 Seed data — @arete/core/db-seed.ts#

db-seed.ts ships three sets of default data for initial database population. Each export ships its own Seed* interface (SeedJournalPrompt, SeedBadge, SeedLevel).

Export Contents
DEFAULT_JOURNAL_PROMPTS 23 system journal prompts across the five prompt categories
DEFAULT_BADGES 17 badge definitions
DEFAULT_LEVELS 10 level definitions

6. API Surface — apps/arete/api#

The API is a Fastify application. buildServer() (src/app.ts) assembles the instance; server.ts starts it. Routes are registered by registerRoutes() (src/routes/index.ts): health probes are unversioned; everything else is mounted under the /v1 prefix.

6.1 Plugins#

src/plugins/ registers plugins in the following order, each decorating the Fastify instance with domain-specific capabilities:

  1. request-context — attaches per-request context for tracing and correlation IDs.
  2. cors — configures cross-origin request handling.
  3. error-handler — normalizes error responses to a consistent JSON shape.
  4. swagger — serves OpenAPI documentation at /documentation.
  5. auth — decorates fastify.authenticate using @fastify/jwt.
  6. database — connects the pg pool and initializes the Drizzle client.
  7. redis — initializes the ioredis client.
  8. rate-limit — applies per-IP rate limiting.
  9. mailer — configures nodemailer for transactional email.
  10. repositories — registers per-domain repository modules (users, habits, goals, journal, vision, time, balance, gamification, coach).

6.2 Health routes (/health*, no auth)#

GET /health, GET /health/ready, GET /health/startup.

6.3 Users — /v1/users#

POST /register, POST /login, POST /logout, GET /me, PATCH /me, PATCH /preferences, GET /me/export, DELETE /me, POST /forgot-password, POST /reset-password, POST /change-password.

6.4 Habits — /v1/habits#

GET /, POST /, GET /today, GET /analytics, GET /:id, PATCH /:id, DELETE /:id, GET /:id/analytics, POST /:id/complete, GET /:id/completions, GET /:id/streak, GET /:id/recovery, POST /:id/friction/analyze, POST /:id/interventions/dispatch, POST /:id/stack.

The friction-analysis and intervention-dispatch endpoints are the V1 contract API — they operate on arete_v1_* tables and accept/return V1 contract schema types.

6.5 Goals — /v1/goals#

GET /, POST /, GET /analytics, GET /okrs, POST /okrs, GET /:id, PATCH /:id, DELETE /:id, POST /:id/progress, GET /:id/hierarchy.

6.6 Journal — /v1/journal#

GET /entries, POST /entries, GET /entries/:id, PATCH /entries/:id, DELETE /entries/:id, GET /prompts, GET /templates, GET /analytics.

6.7 Vision — /v1/vision#

GET /boards, POST /boards, GET /boards/:id, PATCH /boards/:id, DELETE /boards/:id, POST /boards/:id/items, GET /mission, PUT /mission, GET /values, PUT /values.

6.8 Time — /v1/time#

GET /tasks, POST /tasks, PATCH /tasks/:id, DELETE /tasks/:id, GET /weekly-plan, PUT /weekly-plan, GET /daily-plan/:date, PUT /daily-plan/:date, GET /pomodoro, POST /pomodoro/start, POST /pomodoro/complete.

6.9 Balance — /v1/balance#

GET /wheel-of-life, POST /wheel-of-life, GET /wheel-of-life/history, GET /mood, POST /mood, GET /mood/analytics, GET /sleep, POST /sleep, GET /energy, POST /energy.

6.10 Gamification — /v1/gamification#

GET /points, GET /points/transactions, GET /badges, GET /badges/available, GET /level, GET /leaderboards, GET /challenges, POST /challenges/:id/join, GET /accountability-partners, POST /accountability-partners/invite.

6.11 Coach — /v1/coach#

POST /chat, POST /chat/stream (SSE), GET /conversations, GET /recommendations, GET /insights, POST /feedback. The stream endpoint emits tokens at COACH_STREAM_INTERVAL_MS intervals using Server-Sent Events.

6.12 Dashboard — /v1/dashboard#

GET /summary, GET /weekly-activity, GET /recent-moods, POST /mood, GET /profile-stats.

6.13 API metadata#

GET /v1/info (authenticated) returns { name, version, description, environment, domains }, where domains lists habits, goals, journal, vision, time, balance, gamification, coach, affirmations, seven-habits.


7. Events#

The Arete domain does not publish a domain-event stream. There is no event bus, no emit/publish infrastructure, and no event-name constants in libs/arete/* or apps/arete/*. Cross-feature behaviour that would in other systems be event-driven (streak recalculation on completion) is instead handled synchronously by the PostgreSQL trigger in §5.5, and aggregation across features is handled by the dashboard and coach routes querying the database directly.


8. Configuration#

8.1 API environment variables — apps/arete/api/src/config.ts#

loadConfig() parses process.env with a Zod schema; missing values fall back to development defaults. A superRefine rejects the default JWT_SECRET in production and rejects DB_POOL_MIN > DB_POOL_MAX.

Variable Default Notes
PORT 3020 1–65535
HOST 127.0.0.1
NODE_ENV development development/production/test
JWT_SECRET arete-dev-secret-change-me must be overridden in production
JWT_ISSUER arete-api
JWT_ACCESS_TOKEN_TTL 900 (s)
JWT_REFRESH_TOKEN_TTL 604800 (s)
DATABASE_URL postgresql://oshun:oshun_dev@localhost:5432/oshun_dev
DB_POOL_MIN 2
DB_POOL_MAX 10
REDIS_URL redis://localhost:6379
RATE_LIMIT_MAX 100
RATE_LIMIT_WINDOW_MS 60000
LOG_LEVEL info Pino levels
METRICS_PORT 9090
CORS_ORIGIN *
SMTP_HOST 127.0.0.1 Mailpit dev container
SMTP_PORT 1025
SMTP_SECURE false
SMTP_USER / SMTP_PASS (optional)
SMTP_FROM noreply@arete.local
WEB_URL http://localhost:5173 used in password-reset links
COACH_STREAM_INTERVAL_MS 50 per-token SSE delay, 0–2000

8.2 Library build configuration#

  • Project tags (all libraries): ["scope:arete", "layer:domain", "type:lib"]
  • Module format: ESM ("type": "module")
  • Library build executor: @nx/js:tsc
  • Library test executor: @nx/vite:test (per-library vitest.config.ts)
  • @arete/api build/test/dev run via the nx:run-commands executor (tsc, vitest run, tsx watch src/server.ts)

9. Integration Points#

9.1 Internal dependencies#

The dependency boundaries are strict: no feature library imports another feature library. All cross-feature data access flows through the application layer or the database.

  • Every personal-development feature library plus @arete/gamification and @arete/ai-coach depends on @arete/core (declared as a peerDependency).
  • @arete/api depends on @arete/core, @arete/habits, @arete/ai-coach, and shared Oshun libraries (@oshun/auth, @oshun/errors, @oshun/logging, @oshun/metrics, @oshun/tracing).
  • @arete/web depends on @arete/habits.
  • @arete/core depends on @oshun/contracts for the V1 contract types used by the arete_v1_* tables.

9.2 Cross-domain references#

Arete couples to other Oshun domains at a single, well-defined point: the V1 friction-signal and intervention system. The V1 FrictionSignalSourceSchema names veritas, metis, tara, and nyx as domains that can publish friction signals into Arete's habit engine. The V1 InterventionKindSchema includes tara-ritual-surfacing and breathwork-insert as intervention types that surface practices from the Tara domain. Finally, @arete/habits/recovery exports a DEFAULT_TARA_RECOVERY_PRACTICE_REF constant so that Arete recovery prompts can surface a specific Tara practice. These are the only cross-domain couplings expressed in code — all other domain relationships described in the architecture document are conceptual, not code-level.


10. Acceptance Criteria#

A change to the Arete domain is consistent with this specification when all of the following conditions hold:

  1. New entities are added as Zod schemas in @arete/core/schemas.ts (or as V1 contract schemas in @oshun/contracts/arete), with inferred types exported.
  2. New persistent entities have a corresponding Drizzle table in db-schema.ts, registered in ALL_ARETE_TABLES, with relations registered in ALL_ARETE_RELATIONS and any new enum in ALL_ARETE_ENUMS.
  3. New tables use the arete_ prefix and onDelete: 'cascade' for owned data.
  4. New API endpoints are registered through registerRoutes() under /v1, carry a Fastify JSON schema, and require authentication unless deliberately public.
  5. Streak-affecting writes go through arete_habit_completions so the streak trigger fires.
  6. pnpm nx build, lint, and test pass for every affected project.