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 onlyprisma/schema.prismaand a generatedprisma/generated/schema.sql. It has nopackage.jsonorproject.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 |
ValueSchema — id, userId, name (1–100), description (≤2000),
priority (int 1–10, 1 = highest), category (1–100).
RoleSchema — id, 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.
SMARTGoalSchema — GoalSchema 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.
KeyResultSchema — id, okrId (uuid), description (1–1000),
currentValue (number), targetValue (number), unit (1–50), score (number
0.0–1.0).
OKRSchema — id, userId, objective (1–1000), keyResults
(KeyResultSchema[], 1–5), quarter (int 1–4), year (int 2000–2100),
status (GoalStatusSchema, default not_started).
WOOPGoalSchema — id, 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.
ImplementationIntentionSchema — id, 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.
HabitCueSchema — type (enum: time, location, preceding_action,
emotional_state), value (1–500), description (≤1000, default '').
HabitRoutineSchema — steps (array of 1–500-char strings, ≥1),
starterStep (1–500, the tiny first step), durationMinutes (int 1–480),
difficulty (int 1–5).
HabitRewardSchema — type (enum: intrinsic, extrinsic), description
(1–1000), points (int ≥0, default 0).
HabitStackSchema — id, userId, name (1–200), habits (array of
uuid, ≥1, ordered), triggerCue (HabitCueSchema).
HabitCompletionSchema — id, 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).
StreakSchema — id, 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).
StreakFreezeSchema — id, 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 |
JournalPromptSchema — id, text (5–1000), category (enum:
gratitude, reflection, growth, creativity, mindfulness), isSystem
(boolean, default false).
JournalTemplateSchema — id, 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 |
GratitudeItemSchema — text (1–500), category (1–100).
GratitudeEntrySchema — id, 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.
VisionBoardItemSchema — id, boardId (uuid), type (enum: image,
text, goal_link), content (1–5000), position ({ x, y }, both ≥0),
size ({ w, h }, both ≥1), goalId (uuid | null).
VisionBoardSchema — id, 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).
TaskSchema — id, 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 []).
BigRockSchema — id, userId, weekStart (YYYY-MM-DD, Monday),
title (1–500), description (≤2000), roleId (uuid | null), isCompleted
(boolean, default false), priority (int 1–7).
TimeBlockSchema — id, 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).
WeeklyPlanSchema — id, userId, weekStart (YYYY-MM-DD), bigRocks
(BigRockSchema[], default []), roles (array of uuid), review (≤5000),
sharpenTheSaw (≤2000, planned renewal activities).
DailyPlanSchema — id, userId, date (YYYY-MM-DD), bigThree (array
of exactly 3 strings 1–500), timeBlocks (TimeBlockSchema[], default []),
morningRoutine (≤2000), eveningReview (≤2000).
PomodoroSessionSchema — id, 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).
DeepWorkSessionSchema — id, 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.
CircleOfInfluenceSchema — id, userId, item (1–1000), circle (enum:
concern, influence), actionable (boolean, default false), notes
(≤2000).
EmotionalTransactionSchema — id, accountId (uuid), type (enum:
deposit, withdrawal), description (1–1000), amount (int 1–10,
magnitude), category (enum: courtesy, kindness, honesty, commitment,
apology, forgiveness), date (datetime).
EmotionalBankAccountSchema — id, 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.
WheelOfLifeDimensionSchema — dimensionType (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.
WheelOfLifeSchema — id, userId, dimensions
(WheelOfLifeDimensionSchema[], ≥1), overallScore (number 0–10, computed),
assessmentDate (YYYY-MM-DD), notes (≤5000).
RenewalActivitySchema — id, userId, dimension
(WellnessDimensionSchema), activity (1–500), frequencyPerWeek (int 1–14),
durationMinutes (int 1–480), notes (≤2000).
RenewalLogSchema — id, activityId (uuid), userId, date
(YYYY-MM-DD), durationMinutes (int 1–480), quality (int 1–5), notes
(≤2000).
MoodEntrySchema — id, userId, mood (int 1–5), energy (int 1–5),
tags (array of strings 1–50, default []), notes (≤2000), date
(datetime).
3.9 Affirmations#
AffirmationSchema — id, 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.
BadgeSchema — id, 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).
AchievementSchema — id, userId, badgeId (uuid), earnedAt (datetime
| null), progress (number 0–100, default 0).
LevelSchema — level (int 1–100), title (1–200), xpRequired (int ≥0),
xpTotal (int ≥0, cumulative), perks (array of strings 1–500, default []).
PointsSchema — id, userId, amount (int ≥1), type (enum: xp,
coins, gems), source (1–500), earnedAt (datetime).
AccountabilityPartnerSchema — id, userId, partnerUserId (uuid),
status (enum: pending, active, ended, default pending), sharedGoals
(array of uuid, default []), createdAt.
CommitmentContractSchema — id, userId, goalId (uuid), stake
({ description (1–1000), amount (≥0) }), referee (uuid | null), deadline
(YYYY-MM-DD), status (enum: active, completed, failed, default
active).
ChallengeSchema — id, 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_goalscarriessmart_specific,smart_measurable,smart_achievable,smart_relevant,smart_time_bound, andwoop_wish,woop_outcome,woop_obstacle,woop_plandirectly. There are no separatearete_smart_goalsorarete_woop_goalstables. - Goal hierarchy is modelled twice: a self-referential
parent_goal_idonarete_goals, plus an explicitarete_goal_hierarchyjoin table with a unique(parent_goal_id, child_goal_id)index. - Credentials are separated from
arete_users:arete_user_credentialsholds the bcryptpassword_hashso the profile table can beSELECT *'d safely.arete_password_reset_tokensholds single-use, time-bounded reset tokens. - Habit
cue/routine/rewardare stored as JSONB columns onarete_habits, not separate tables. - Mood, sleep, energy are separate tables (
arete_mood_entries,arete_sleep_entries,arete_energy_entries), each with asequencecolumn so multiple same-day entries are ordered. arete_habit_completionscarries 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_invitationsrecords 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:
- Skip rows where
skipped = true— a recorded skip does not affect the streak. - Create a streak row for the habit if none exists yet.
- Compute the day gap between the current insertion date and
last_completion_date. - If the gap is 1 day (consecutive), increment
currentby 1. - If the gap is within the forgiveness window, consume a forgiveness day and increment.
- If the gap exceeds the forgiveness window, reset
currentto 1. - Update
bestifcurrentnow exceeds it. - Write the new values back to both
arete_streaksand the denormalized fields onarete_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:
request-context— attaches per-request context for tracing and correlation IDs.cors— configures cross-origin request handling.error-handler— normalizes error responses to a consistent JSON shape.swagger— serves OpenAPI documentation at/documentation.auth— decoratesfastify.authenticateusing@fastify/jwt.database— connects thepgpool and initializes the Drizzle client.redis— initializes theioredisclient.rate-limit— applies per-IP rate limiting.mailer— configuresnodemailerfor transactional email.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-libraryvitest.config.ts) @arete/apibuild/test/dev run via thenx:run-commandsexecutor (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/gamificationand@arete/ai-coachdepends on@arete/core(declared as apeerDependency). @arete/apidepends on@arete/core,@arete/habits,@arete/ai-coach, and shared Oshun libraries (@oshun/auth,@oshun/errors,@oshun/logging,@oshun/metrics,@oshun/tracing).@arete/webdepends on@arete/habits.@arete/coredepends on@oshun/contractsfor the V1 contract types used by thearete_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:
- 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. - New persistent entities have a corresponding Drizzle table in
db-schema.ts, registered inALL_ARETE_TABLES, with relations registered inALL_ARETE_RELATIONSand any new enum inALL_ARETE_ENUMS. - New tables use the
arete_prefix andonDelete: 'cascade'for owned data. - New API endpoints are registered through
registerRoutes()under/v1, carry a Fastify JSON schema, and require authentication unless deliberately public. - Streak-affecting writes go through
arete_habit_completionsso the streak trigger fires. pnpm nx build,lint, andtestpass for every affected project.