## 1. Schema - [x] 1.1 Add `visibility text NOT NULL DEFAULT 'private'` to `journal.routes` in `packages/db/src/schema/journal.ts` - [x] 1.2 Add the same column to `journal.activities` in the same file - [x] 1.3 Export a shared type `type Visibility = 'private' | 'unlisted' | 'public'` from `packages/db/src/schema/journal.ts` (or a small adjacent module) and reuse at the app layer ## 2. Server-side access helper - [x] 2.1 Add `canView(content, user)` in `apps/journal/app/lib/auth.server.ts` that returns `true` for `public`, `true` for `unlisted` (the direct-URL case — callers pass `true` when routed to a detail page, `false` when generating listings), and ownership-checked otherwise - [x] 2.2 Unit test the three matrix cells ## 3. Route detail access - [x] 3.1 Update `apps/journal/app/routes/routes.$id.tsx` loader: fetch route, then apply `canView`; return 404 when not allowed - [x] 3.2 Expose `visibility` on the loader's returned shape so the component can render the current-visibility badge to the owner - [x] 3.3 Emit Open Graph / Twitter Card `meta` for `public` and `unlisted` routes (title, description, `og:type="article"`, `og:site_name="trails.cool"`, `twitter:card="summary"`) ## 4. Activity detail access - [x] 4.1 Mirror 3.1 in `apps/journal/app/routes/activities.$id.tsx` - [x] 4.2 Mirror 3.3 for activities ## 5. Visibility selector in the edit flow - [x] 5.1 Add a visibility `