{
  "$schema": "https://pointcast.xyz/me.json",
  "name": "PointCast Me",
  "description": "Personal PointCast check-in cockpit for browser-local receipts, active inventory, and linked identity rails.",
  "generatedAt": "2026-07-13T06:56:04.877Z",
  "human": "https://pointcast.xyz/me",
  "identityModel": {
    "localFirst": true,
    "profileStorage": "pc:checkins:profile",
    "receiptStorage": "pc:checkins:log",
    "inventoryStorage": "pc:checkins:inventory",
    "activeObjectStorage": "pc:checkins:active-object",
    "activeObjectUpdatedAtStorage": "pc:checkins:active-object-updated-at",
    "linkedIdentityStorage": "pc:identity:links",
    "browserIdentityStorage": "pc:me:id",
    "sessionEndpoint": "https://pointcast.xyz/api/auth/session",
    "stateEndpoint": "https://pointcast.xyz/api/me/state",
    "serverStorageKey": "me:{userId}:state",
    "stateVersion": 1,
    "anonymousMode": "If USERS is unbound or the visitor is not signed in, /me remains fully browser-local.",
    "mergeBehavior": {
      "receipts": "Deduped by id; server record is preserved on conflict.",
      "inventoryAdditions": "Deduped by id; server record is preserved on conflict.",
      "profile": "Latest profile.savedAt wins.",
      "activeObject": "Latest activeObjectUpdatedAt wins.",
      "writeBack": "After hydration, merged state is written to both localStorage and /api/me/state when authenticated."
    },
    "stateShape": {
      "version": 1,
      "fields": [
        "profile",
        "inventoryAdditions",
        "activeObjectId",
        "activeObjectUpdatedAt",
        "receipts",
        "linkedIdentities",
        "updatedAt"
      ]
    }
  },
  "authProviders": [
    {
      "id": "browser",
      "label": "Browser",
      "rail": "local device identity",
      "status": "local-live",
      "storage": "pc:me:id",
      "note": "Instant local identity for check-ins before server auth is linked."
    },
    {
      "id": "google",
      "label": "Google",
      "rail": "account login",
      "status": "server-scaffold",
      "storage": "pc:identity:links",
      "route": "/api/auth/google",
      "note": "OAuth start and callback routes are wired; Cloudflare env plus USERS KV make it production-live."
    },
    {
      "id": "metamask",
      "label": "MetaMask",
      "rail": "EVM wallet",
      "status": "signature-live",
      "storage": "pc:identity:links",
      "route": "/api/auth/ethereum",
      "note": "MetaMask signs a PointCast login message and /api/auth/ethereum verifies it before syncing /me."
    },
    {
      "id": "tezos",
      "label": "Tezos",
      "rail": "Beacon / Kukai wallet",
      "status": "signature-live",
      "storage": "pc:wallet",
      "route": "/api/auth/tezos",
      "note": "Beacon wallet connection and Tezos signature verification are the strongest current auth path."
    }
  ],
  "authStatus": {
    "browser": "live locally in localStorage",
    "tezos": "Beacon wallet connection and /api/auth/tezos signature verification are present with USERS-backed nonce replay protection",
    "google": "OAuth start and callback exchange are wired; requires Google env vars and USERS KV for production sessions",
    "metamask": "/api/auth/ethereum verifies PointCast signed messages with viem, address/origin/TTL/chain checks, and USERS-backed nonce replay protection"
  },
  "authFailureReasons": {
    "kvNotBound": "kv-not-bound",
    "badEthereumSignature": "invalid-signature",
    "staleSignedMessage": "stale-message",
    "nonceReplay": "nonce-reused"
  },
  "profileFields": [
    {
      "id": "displayName",
      "label": "Display name",
      "required": true
    },
    {
      "id": "homeBase",
      "label": "Home base",
      "required": true
    },
    {
      "id": "defaultScope",
      "label": "Default scope",
      "required": false
    },
    {
      "id": "usualPlace",
      "label": "Usual place",
      "required": false
    },
    {
      "id": "currentObject",
      "label": "Current object or paddle",
      "required": false
    },
    {
      "id": "publicNote",
      "label": "Public note",
      "required": false
    }
  ],
  "storageKeys": {
    "profile": "pc:checkins:profile",
    "log": "pc:checkins:log",
    "inventory": "pc:checkins:inventory",
    "activeObject": "pc:checkins:active-object",
    "activeObjectUpdatedAt": "pc:checkins:active-object-updated-at",
    "identityLinks": "pc:identity:links",
    "meId": "pc:me:id",
    "wallet": "pc:wallet",
    "wallets": "pc:wallets",
    "walletActive": "pc:wallet-active"
  },
  "scopes": [
    {
      "id": "local",
      "label": "Local",
      "station": "South Bay handoff layer",
      "distance": "0-25 miles",
      "frame": "Courts, coffee, walks, local tables, paddle loans, honey, and anything someone can actually bring back next week.",
      "receipt": "A place, an object, a person or crew, one useful note, and whether the thing should repeat.",
      "color": "#0f6258",
      "wash": "#e7f4ef"
    },
    {
      "id": "national",
      "label": "National",
      "station": "Traveling field desk",
      "distance": "United States",
      "frame": "Tournaments, airports, road trips, visiting courts, city shelves, campus clubs, and creator tables that can become remote PointCast nodes.",
      "receipt": "What traveled well, what broke, what should be copied locally, and who else should see it.",
      "color": "#185fa5",
      "wash": "#eef4fa"
    },
    {
      "id": "global",
      "label": "Global",
      "station": "World signal map",
      "distance": "everywhere else",
      "frame": "Objects, places, ideas, collector rooms, court rituals, civic patterns, and small durable practices worth translating across borders.",
      "receipt": "The local custom, the portable pattern, the object that carried it, and the translation note.",
      "color": "#8a4f12",
      "wash": "#fff3de"
    }
  ],
  "inventory": [
    {
      "id": "11six24-vapor-power-2",
      "name": "11SIX24 Vapor Power 2",
      "maker": "11SIX24",
      "category": "paddle",
      "owner": "Mike",
      "status": "daily-driver",
      "scope": "local",
      "feel": "controlled power, spin, confident counters",
      "use": "Baseline drives, third-shot roll practice, and doubles games where the paddle should feel settled.",
      "placeSignal": "Start every Paddle Tide shelf with the paddle Mike actually plays.",
      "tags": [
        "pickleball",
        "paddle",
        "daily driver",
        "south bay"
      ]
    },
    {
      "id": "honolulu-jnfk",
      "name": "Honolulu JNFK",
      "maker": "Honolulu",
      "category": "paddle",
      "owner": "Mike",
      "status": "rotation",
      "scope": "local",
      "feel": "foam-core curiosity, touch window, comparison notes",
      "use": "Dink exchanges, kitchen resets, and side-by-side trials with the Vapor.",
      "placeSignal": "A court check-in can say what changed in the first ten minutes.",
      "tags": [
        "pickleball",
        "paddle",
        "trial",
        "court craft"
      ]
    },
    {
      "id": "gearbox-g2-power",
      "name": "Gearbox G2 Power",
      "maker": "Gearbox",
      "category": "paddle",
      "owner": "Mike",
      "status": "rotation",
      "scope": "national",
      "feel": "power reference, compact notes, travel comparison",
      "use": "A national benchmark paddle for road games, visitor bags, and tournament-adjacent comparisons.",
      "placeSignal": "Useful when PointCast wants to compare a local court feel with a broader rec-play baseline.",
      "tags": [
        "pickleball",
        "paddle",
        "power",
        "travel kit"
      ]
    },
    {
      "id": "vatic-prism-14mm",
      "name": "Vatic Prism 14mm",
      "maker": "Vatic",
      "category": "paddle",
      "owner": "Mike",
      "status": "loanable",
      "scope": "local",
      "feel": "accessible control, loaner-friendly, quick handoff",
      "use": "Starter shelf, friend loan, UES Court Craft demo, and return-tag check-ins.",
      "placeSignal": "A good loaner makes the inventory layer feel generous instead of gear-obsessed.",
      "tags": [
        "pickleball",
        "paddle",
        "loaner",
        "library"
      ]
    },
    {
      "id": "franklin-paddle-specs-pending",
      "name": "Franklin paddle",
      "maker": "Franklin",
      "category": "paddle",
      "owner": "Mike",
      "status": "rotation",
      "scope": "local",
      "feel": "new pickup, specs pending, needs first court notes",
      "use": "Identify the exact model, capture the handle/packaging specs, then compare it against the current paddle shelf.",
      "placeSignal": "A good first /me check-in should say which Franklin model this is and what changed on court.",
      "tags": [
        "pickleball",
        "paddle",
        "franklin",
        "specs pending"
      ],
      "specs": {
        "model": "pending",
        "thickness": "pending",
        "weight": "pending",
        "length": "pending",
        "width": "pending",
        "core": "pending",
        "face": "pending",
        "certification": "pending",
        "source": "confirm from paddle model, packaging, or Franklin product page",
        "notes": "User picked up a new Franklin paddle; exact model has not been captured yet."
      }
    },
    {
      "id": "pointcast-field-card",
      "name": "PointCast field card",
      "maker": "PointCast",
      "category": "publication",
      "owner": "PointCast",
      "status": "reference",
      "scope": "global",
      "feel": "tiny receipt, civic memory, portable context",
      "use": "A postcard-sized way to mark a check-in: place, object, person, one useful note.",
      "placeSignal": "Turns any local moment into a repeatable protocol without making it heavy.",
      "tags": [
        "receipt",
        "publication",
        "field note",
        "global"
      ]
    },
    {
      "id": "travel-shelf-slot",
      "name": "Travel shelf slot",
      "maker": "PointCast",
      "category": "shelf",
      "owner": "Open",
      "status": "wanted",
      "scope": "national",
      "feel": "one object carried from city to city",
      "use": "A small open slot for whatever should be checked in on the next road day.",
      "placeSignal": "Makes national check-ins more than location pins: the object changes the story.",
      "tags": [
        "travel",
        "shelf",
        "inventory",
        "wanted"
      ]
    }
  ],
  "places": [
    {
      "id": "recreation-park",
      "scope": "local",
      "name": "Recreation Park",
      "region": "El Segundo, CA",
      "kind": "court",
      "status": "active",
      "signal": "Default court language for Paddle Tide: doubles, warmups, loaner handoffs, and post-game receipts.",
      "inventoryHook": "Paddles, balls, return tags, court notes.",
      "nextCheckin": "Run one Vapor vs Vatic comparison and log who should borrow which paddle."
    },
    {
      "id": "el-segundo-brewing",
      "scope": "local",
      "name": "El Segundo Brewing",
      "region": "El Segundo, CA",
      "kind": "table",
      "status": "seed",
      "signal": "The after-court place where a paddle note can become a block, a meetup, or a Honey League receipt.",
      "inventoryHook": "Postcards, tasting notes, local route cards.",
      "nextCheckin": "Capture one table note that connects a court session to a local business."
    },
    {
      "id": "big-mikes",
      "scope": "local",
      "name": "Big Mike's",
      "region": "El Segundo, CA",
      "kind": "coffee",
      "status": "seed",
      "signal": "Morning check-ins can start with coffee, not a meeting invite.",
      "inventoryHook": "Field card, pen, session prompt.",
      "nextCheckin": "Write the first coffee-to-court inventory receipt."
    },
    {
      "id": "road-court",
      "scope": "national",
      "name": "Road Court",
      "region": "US travel shelf",
      "kind": "travel court",
      "status": "candidate",
      "signal": "Any court visited outside the South Bay gets the same receipt shape, so local habits can travel without pretending every city is the same.",
      "inventoryHook": "Travel paddle, city note, visitor bag.",
      "nextCheckin": "Compare the local loaner shelf against the first out-of-town court bag."
    },
    {
      "id": "tournament-tent",
      "scope": "national",
      "name": "Tournament Tent",
      "region": "US event circuit",
      "kind": "event",
      "status": "candidate",
      "signal": "A national check-in should capture equipment, weather, waiting, formats, and the little systems players copy.",
      "inventoryHook": "Demo paddles, grip tape, water, repair kit.",
      "nextCheckin": "Log one practical thing rec players can steal from an event setup."
    },
    {
      "id": "sister-court",
      "scope": "global",
      "name": "Sister Court",
      "region": "global pickleball node",
      "kind": "court",
      "status": "candidate",
      "signal": "A global place becomes interesting when it keeps its own local customs instead of becoming a generic map pin.",
      "inventoryHook": "Borrowed paddle, etiquette note, local phrase.",
      "nextCheckin": "Record the ritual before recording the score."
    },
    {
      "id": "world-table",
      "scope": "global",
      "name": "World Table",
      "region": "collector and maker rooms",
      "kind": "table",
      "status": "candidate",
      "signal": "The non-sports version: a table where someone brings an object, a receipt, and a reason it matters.",
      "inventoryHook": "Collected object, token, zine, snack, tool.",
      "nextCheckin": "Translate one object into a PointCast field card."
    }
  ],
  "goals": [
    {
      "scope": "local",
      "title": "Make ten real handoffs visible",
      "target": "10 local check-ins",
      "metric": "profile + place + object + one return loop",
      "why": "Local gets good when people can point to the paddle, table, or route and say what happened."
    },
    {
      "scope": "national",
      "title": "Turn travel into a reusable field desk",
      "target": "5 national comparison notes",
      "metric": "what traveled, what failed, what should be copied locally",
      "why": "National check-ins keep PointCast from becoming only hometown texture."
    },
    {
      "scope": "global",
      "title": "Translate one small custom per place",
      "target": "3 global pattern notes",
      "metric": "custom + object + translation note",
      "why": "Global is interesting when it preserves difference and still gives the network a portable shape."
    }
  ],
  "adjacent": {
    "checkins": "https://pointcast.xyz/checkins",
    "checkinsJson": "https://pointcast.xyz/checkins.json",
    "profile": "https://pointcast.xyz/profile",
    "places": "https://pointcast.xyz/places",
    "placesJson": "https://pointcast.xyz/places.json",
    "goal": "https://pointcast.xyz/goal",
    "goalJson": "https://pointcast.xyz/goal.json",
    "paddleExchange": "https://pointcast.xyz/paddle-exchange"
  }
}