@ima-jin/config 0.8.22 → 0.8.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -26,6 +26,7 @@ __export(index_exports, {
26
26
  HANDLE_ERROR: () => HANDLE_ERROR,
27
27
  HANDLE_INPUT_PATTERN: () => HANDLE_INPUT_PATTERN,
28
28
  HANDLE_PATTERN: () => HANDLE_PATTERN,
29
+ IDENTITY_CATEGORIES: () => IDENTITY_CATEGORIES,
29
30
  RESERVED_HANDLES: () => RESERVED_HANDLES,
30
31
  SERVICES: () => SERVICES,
31
32
  SERVICE_NAMES: () => SERVICE_NAMES,
@@ -210,17 +211,14 @@ var SERVICES = [
210
211
  { name: "media", label: "Media", icon: "\u{1F4C1}", description: "Files, images, and .fair attribution", devPort: 3e3, prodPort: 7e3, schema: "media", tier: "core", visibility: "authenticated", category: "kernel" },
211
212
  { name: "registry", label: "Registry", icon: "\u{1F4E1}", description: "Service registry and DFOS relay", devPort: 3e3, prodPort: 7e3, schema: "registry", tier: "core", visibility: "public", category: "kernel" },
212
213
  { name: "notify", label: "Notify", icon: "\u{1F514}", description: "Notifications and preferences", devPort: 3e3, prodPort: 7e3, schema: "notify", tier: "core", visibility: "internal", category: "kernel" },
213
- { name: "usage", label: "Usage", icon: "\u{1F4CA}", description: "Inference cost ledger \u2014 incurred, billed, drift, signed rollup", devPort: 3e3, prodPort: 7e3, schema: "usage", tier: "core", visibility: "authenticated", category: "kernel" },
214
- { name: "calendar", label: "Calendar", icon: "\u{1F4C5}", description: "Temporal entries \u2014 availability, meetings, events, and reminders", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "authenticated", category: "kernel" },
214
+ { name: "usage", label: "Usage", icon: "\u{1F4CA}", description: "Inference cost ledger \u2014 incurred, billed, drift, signed rollup", devPort: 3e3, prodPort: 7e3, schema: "usage", tier: "core", visibility: "internal", category: "kernel" },
215
+ { name: "calendar", label: "Calendar", icon: "\u{1F4C5}", description: "Temporal entries \u2014 availability, meetings, events, and reminders", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "internal", category: "kernel" },
215
216
  { name: "jin", label: "Jin", icon: "\u{1F9ED}", description: "Operator dashboard \u2014 signed approvals, proposals, and usage feed", devPort: 3e3, prodPort: 7e3, schema: "operator", tier: "core", visibility: "internal", category: "kernel" },
216
- { name: "google", label: "Google Workspace", icon: "\u{1F4E8}", description: "Gmail/Calendar/Drive/Meet connector \u2014 OAuth2 auth-code, sealed refresh token", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "authenticated", category: "kernel" },
217
+ { name: "google", label: "Google Workspace", icon: "\u{1F4E8}", description: "Gmail/Calendar/Drive/Meet connector \u2014 OAuth2 auth-code, sealed refresh token", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "internal", category: "kernel" },
217
218
  { name: "vault", label: "Vault", icon: "\u{1F510}", description: "Sealed secrets, delegation grants, and vault-minted service credentials", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "internal", category: "kernel" },
218
- // Core apps — separate processes
219
+ // Standalone URL/port contracts for non-nav callers (health probes,
220
+ // buildPublicUrlAbsolute, check-env). Registry placements decide nav.
219
221
  { name: "events", label: "Events", icon: "\u{1F3AB}", description: "Event creation, ticketing, and management", devPort: 3006, prodPort: 7006, schema: "events", tier: "core", visibility: "public", category: "core" },
220
- // Imajin apps
221
- { name: "coffee", label: "Coffee", icon: "\u2615", description: "Tipping and creator support pages", devPort: 3100, prodPort: 7100, schema: "coffee", tier: "imajin", visibility: "creator", category: "creator" },
222
- { name: "dykil", label: "Surveys", icon: "\u{1F4CB}", description: "Surveys and do-you-know-if-I-like polls", devPort: 3101, prodPort: 7101, schema: "dykil", tier: "imajin", visibility: "creator", category: "creator" },
223
- { name: "links", label: "Links", icon: "\u{1F517}", description: "Link-in-bio pages and click tracking", devPort: 3102, prodPort: 7102, schema: "links", tier: "imajin", visibility: "creator", category: "creator" },
224
222
  { name: "learn", label: "Learn", icon: "\u{1F4DA}", description: "Courses, lessons, and learning progress", devPort: 3103, prodPort: 7103, schema: "learn", tier: "imajin", visibility: "public", category: "core" },
225
223
  { name: "market", label: "Market", icon: "\u{1F3EA}", description: "Local commerce \u2014 buy and sell with trust", devPort: 3104, prodPort: 7104, schema: "market", tier: "imajin", visibility: "public", category: "core" },
226
224
  // Meta — project info and external resources surfaced in the launcher
@@ -355,6 +353,25 @@ function tier3Headers() {
355
353
  // src/brand.ts
356
354
  var APP_DISPLAY_NAME = "imajin (\u03B1)";
357
355
 
356
+ // src/identity-categories.ts
357
+ var IDENTITY_CATEGORIES = [
358
+ "caf\xE9",
359
+ "restaurant",
360
+ "shop",
361
+ "venue",
362
+ "studio",
363
+ "bar",
364
+ "gallery",
365
+ "gym",
366
+ "contractor",
367
+ "trades",
368
+ "professional services",
369
+ "health",
370
+ "education",
371
+ "technology",
372
+ "nonprofit"
373
+ ];
374
+
358
375
  // src/session.ts
359
376
  function getSessionCookieName(env) {
360
377
  const resolved = env ?? (typeof process !== "undefined" && (process.env.IMAJIN_ENV === "dev" || process.env.NODE_ENV === "development") ? "dev" : "prod");
@@ -367,8 +384,7 @@ function isLocalhost() {
367
384
  return prefix.includes("localhost");
368
385
  }
369
386
  function isHostScoped() {
370
- if (typeof process === "undefined") return false;
371
- return process.env.SESSION_COOKIE_SCOPE === "host";
387
+ return typeof process === "undefined" || process.env.SESSION_COOKIE_SCOPE !== "domain";
372
388
  }
373
389
  function getSessionCookieOptions(env) {
374
390
  const local = isLocalhost();
@@ -649,6 +665,7 @@ var notifySettingsPath = () => `/notify/settings`;
649
665
  HANDLE_ERROR,
650
666
  HANDLE_INPUT_PATTERN,
651
667
  HANDLE_PATTERN,
668
+ IDENTITY_CATEGORIES,
652
669
  RESERVED_HANDLES,
653
670
  SERVICES,
654
671
  SERVICE_NAMES,
package/dist/index.d.cts CHANGED
@@ -80,6 +80,14 @@ declare function tier3Headers(): HeaderEntry[];
80
80
  */
81
81
  declare const APP_DISPLAY_NAME = "imajin (\u03B1)";
82
82
 
83
+ /**
84
+ * Shared organization/place category taxonomy.
85
+ * Values are persisted in profile metadata: keep existing spellings stable,
86
+ * especially `café`, and extend this vocabulary rather than individual pickers.
87
+ * This is a suggestion vocabulary, not a validator for historical custom values.
88
+ */
89
+ declare const IDENTITY_CATEGORIES: readonly ["café", "restaurant", "shop", "venue", "studio", "bar", "gallery", "gym", "contractor", "trades", "professional services", "health", "education", "technology", "nonprofit"];
90
+
83
91
  /**
84
92
  * Canonical service manifest — infra/build-time topology for all Imajin
85
93
  * services (dev/prod ports, Postgres schema, deployment tier, Caddy/pm2
@@ -188,15 +196,14 @@ declare function buildServiceUrlMap(env: Record<string, string | undefined>, mod
188
196
  declare function getSessionCookieName(env?: "dev" | "prod"): string;
189
197
  /** Default cookie name — resolves at import time based on environment */
190
198
  declare const SESSION_COOKIE_NAME: string;
191
- /** Cookie options for cross-subdomain sessions.
199
+ /** Cookie options for host-only sessions (with explicit domain rollback).
192
200
  * When called with no argument, auto-detects from IMAJIN_ENV (same logic as getSessionCookieName).
193
201
  * Accepts optional "dev" | "prod" override for explicit control.
194
202
  *
195
203
  * Localhost-aware: when SERVICE_PREFIX contains "localhost", uses
196
204
  * settings compatible with HTTP on localhost (no domain, not secure, lax sameSite).
197
205
  *
198
- * See {@link isHostScoped} for the `SESSION_COOKIE_SCOPE=host` opt-in that
199
- * narrows the deployed cookie to host-only instead of `.imajin.ai`.
206
+ * `SESSION_COOKIE_SCOPE=domain` restores the deployed parent-domain cookie.
200
207
  */
201
208
  declare function getSessionCookieOptions(env?: "dev" | "prod"): {
202
209
  name: string;
@@ -481,4 +488,4 @@ declare const projectPath: () => string;
481
488
  declare const notifyPath: () => string;
482
489
  declare const notifySettingsPath: () => string;
483
490
 
484
- export { ALLOWED_FRAME_ORIGINS, APP_DISPLAY_NAME, type ForestScopeConfig, HANDLE_ALLOWED_CHARS, HANDLE_ERROR, HANDLE_INPUT_PATTERN, HANDLE_PATTERN, type NodeSelfInfo, RESERVED_HANDLES, SERVICES, SERVICE_NAMES, SESSION_COOKIE_NAME, type ServiceCategory, type ServiceDefinition, type ServiceTier, type ServiceVisibility, type StandaloneDashboardMiddlewareOptions, apiFetch, apiUrl, articleAuthorPath, articlePath, articlesPath, authAgentsPath, authAppsPath, authAttestationsPath, authAuthorizePath, authDeveloperAppPath, authDeveloperAppsPath, authGroupSettingsPath, authGroupsPath, authLoginPath, authMembersPath, authNewGroupPath, authNewStubPath, authNotificationsPath, authOnboardPath, authRegisterPath, authSecurityPath, authSettingsPath, authStubsPath, bugsAdminPath, bugsPath, buildPath, buildPublicUrl, buildPublicUrlAbsolute, buildServiceUrlMap, bumpPath, chatConversationPath, chatConversationsPath, chatPath, coffeeDashboardPath, coffeeEditPath, coffeeHandlePath, coffeeSuccessPath, connectionsInvitePath, connectionsPath, connectionsPodPath, corsHeaders, corsOptions, developerGuidePath, docsPath, dykilCreatePath, dykilDashboardPath, dykilEmbedPath, dykilHandlePath, dykilResultsPath, dykilSurveyPath, eventAdminPath, eventCheckoutSuccessPath, eventEditPath, eventEditUrl, eventMyTicketsPath, eventMyTicketsUrl, eventPath, eventRegisterPath, eventRegisterUrl, eventUrl, eventsAdminListPath, eventsCheckoutSuccessPath, eventsCreatePath, eventsDashboardPath, getClientIP, getForestScopeConfig, getNodeSelf, getPort, getPublicUrl, getService, getServiceUrl, getSessionCookieName, getSessionCookieOptions, hasRegistryServiceUrl, healthPath, isAllowedOrigin, isReservedHandle, isValidHandle, learnCourseDashboardPath, learnCourseLessonPath, learnCoursePath, learnCoursePresentPath, learnCourseStudentsPath, learnDashboardPath, learnHandlePath, linksDashboardPath, linksEditPath, linksHandlePath, marketCheckoutSuccessPath, marketDashboardPath, marketListingEditPath, marketListingPath, marketNewListingPath, marketSellerPath, marketSettingsPath, mediaPath, normalizeHandleInput, notifyPath, notifySettingsPath, payHistoryPath, payPath, payTopupPath, payTopupSuccessPath, privacyPath, profileEditPath, profileLoginPath, profilePath, profileRegisterPath, profileUrl, projectPath, rateLimit, registryDocsPath, registryPath, registryServiceUrl, servicesByTier, servicesByVisibility, standaloneDashboardMiddleware, subscribePath, tier1Headers, tier2Headers, tier3Headers, validateOrigin, whitepaperPath, withCors };
491
+ export { ALLOWED_FRAME_ORIGINS, APP_DISPLAY_NAME, type ForestScopeConfig, HANDLE_ALLOWED_CHARS, HANDLE_ERROR, HANDLE_INPUT_PATTERN, HANDLE_PATTERN, IDENTITY_CATEGORIES, type NodeSelfInfo, RESERVED_HANDLES, SERVICES, SERVICE_NAMES, SESSION_COOKIE_NAME, type ServiceCategory, type ServiceDefinition, type ServiceTier, type ServiceVisibility, type StandaloneDashboardMiddlewareOptions, apiFetch, apiUrl, articleAuthorPath, articlePath, articlesPath, authAgentsPath, authAppsPath, authAttestationsPath, authAuthorizePath, authDeveloperAppPath, authDeveloperAppsPath, authGroupSettingsPath, authGroupsPath, authLoginPath, authMembersPath, authNewGroupPath, authNewStubPath, authNotificationsPath, authOnboardPath, authRegisterPath, authSecurityPath, authSettingsPath, authStubsPath, bugsAdminPath, bugsPath, buildPath, buildPublicUrl, buildPublicUrlAbsolute, buildServiceUrlMap, bumpPath, chatConversationPath, chatConversationsPath, chatPath, coffeeDashboardPath, coffeeEditPath, coffeeHandlePath, coffeeSuccessPath, connectionsInvitePath, connectionsPath, connectionsPodPath, corsHeaders, corsOptions, developerGuidePath, docsPath, dykilCreatePath, dykilDashboardPath, dykilEmbedPath, dykilHandlePath, dykilResultsPath, dykilSurveyPath, eventAdminPath, eventCheckoutSuccessPath, eventEditPath, eventEditUrl, eventMyTicketsPath, eventMyTicketsUrl, eventPath, eventRegisterPath, eventRegisterUrl, eventUrl, eventsAdminListPath, eventsCheckoutSuccessPath, eventsCreatePath, eventsDashboardPath, getClientIP, getForestScopeConfig, getNodeSelf, getPort, getPublicUrl, getService, getServiceUrl, getSessionCookieName, getSessionCookieOptions, hasRegistryServiceUrl, healthPath, isAllowedOrigin, isReservedHandle, isValidHandle, learnCourseDashboardPath, learnCourseLessonPath, learnCoursePath, learnCoursePresentPath, learnCourseStudentsPath, learnDashboardPath, learnHandlePath, linksDashboardPath, linksEditPath, linksHandlePath, marketCheckoutSuccessPath, marketDashboardPath, marketListingEditPath, marketListingPath, marketNewListingPath, marketSellerPath, marketSettingsPath, mediaPath, normalizeHandleInput, notifyPath, notifySettingsPath, payHistoryPath, payPath, payTopupPath, payTopupSuccessPath, privacyPath, profileEditPath, profileLoginPath, profilePath, profileRegisterPath, profileUrl, projectPath, rateLimit, registryDocsPath, registryPath, registryServiceUrl, servicesByTier, servicesByVisibility, standaloneDashboardMiddleware, subscribePath, tier1Headers, tier2Headers, tier3Headers, validateOrigin, whitepaperPath, withCors };
package/dist/index.d.ts CHANGED
@@ -80,6 +80,14 @@ declare function tier3Headers(): HeaderEntry[];
80
80
  */
81
81
  declare const APP_DISPLAY_NAME = "imajin (\u03B1)";
82
82
 
83
+ /**
84
+ * Shared organization/place category taxonomy.
85
+ * Values are persisted in profile metadata: keep existing spellings stable,
86
+ * especially `café`, and extend this vocabulary rather than individual pickers.
87
+ * This is a suggestion vocabulary, not a validator for historical custom values.
88
+ */
89
+ declare const IDENTITY_CATEGORIES: readonly ["café", "restaurant", "shop", "venue", "studio", "bar", "gallery", "gym", "contractor", "trades", "professional services", "health", "education", "technology", "nonprofit"];
90
+
83
91
  /**
84
92
  * Canonical service manifest — infra/build-time topology for all Imajin
85
93
  * services (dev/prod ports, Postgres schema, deployment tier, Caddy/pm2
@@ -188,15 +196,14 @@ declare function buildServiceUrlMap(env: Record<string, string | undefined>, mod
188
196
  declare function getSessionCookieName(env?: "dev" | "prod"): string;
189
197
  /** Default cookie name — resolves at import time based on environment */
190
198
  declare const SESSION_COOKIE_NAME: string;
191
- /** Cookie options for cross-subdomain sessions.
199
+ /** Cookie options for host-only sessions (with explicit domain rollback).
192
200
  * When called with no argument, auto-detects from IMAJIN_ENV (same logic as getSessionCookieName).
193
201
  * Accepts optional "dev" | "prod" override for explicit control.
194
202
  *
195
203
  * Localhost-aware: when SERVICE_PREFIX contains "localhost", uses
196
204
  * settings compatible with HTTP on localhost (no domain, not secure, lax sameSite).
197
205
  *
198
- * See {@link isHostScoped} for the `SESSION_COOKIE_SCOPE=host` opt-in that
199
- * narrows the deployed cookie to host-only instead of `.imajin.ai`.
206
+ * `SESSION_COOKIE_SCOPE=domain` restores the deployed parent-domain cookie.
200
207
  */
201
208
  declare function getSessionCookieOptions(env?: "dev" | "prod"): {
202
209
  name: string;
@@ -481,4 +488,4 @@ declare const projectPath: () => string;
481
488
  declare const notifyPath: () => string;
482
489
  declare const notifySettingsPath: () => string;
483
490
 
484
- export { ALLOWED_FRAME_ORIGINS, APP_DISPLAY_NAME, type ForestScopeConfig, HANDLE_ALLOWED_CHARS, HANDLE_ERROR, HANDLE_INPUT_PATTERN, HANDLE_PATTERN, type NodeSelfInfo, RESERVED_HANDLES, SERVICES, SERVICE_NAMES, SESSION_COOKIE_NAME, type ServiceCategory, type ServiceDefinition, type ServiceTier, type ServiceVisibility, type StandaloneDashboardMiddlewareOptions, apiFetch, apiUrl, articleAuthorPath, articlePath, articlesPath, authAgentsPath, authAppsPath, authAttestationsPath, authAuthorizePath, authDeveloperAppPath, authDeveloperAppsPath, authGroupSettingsPath, authGroupsPath, authLoginPath, authMembersPath, authNewGroupPath, authNewStubPath, authNotificationsPath, authOnboardPath, authRegisterPath, authSecurityPath, authSettingsPath, authStubsPath, bugsAdminPath, bugsPath, buildPath, buildPublicUrl, buildPublicUrlAbsolute, buildServiceUrlMap, bumpPath, chatConversationPath, chatConversationsPath, chatPath, coffeeDashboardPath, coffeeEditPath, coffeeHandlePath, coffeeSuccessPath, connectionsInvitePath, connectionsPath, connectionsPodPath, corsHeaders, corsOptions, developerGuidePath, docsPath, dykilCreatePath, dykilDashboardPath, dykilEmbedPath, dykilHandlePath, dykilResultsPath, dykilSurveyPath, eventAdminPath, eventCheckoutSuccessPath, eventEditPath, eventEditUrl, eventMyTicketsPath, eventMyTicketsUrl, eventPath, eventRegisterPath, eventRegisterUrl, eventUrl, eventsAdminListPath, eventsCheckoutSuccessPath, eventsCreatePath, eventsDashboardPath, getClientIP, getForestScopeConfig, getNodeSelf, getPort, getPublicUrl, getService, getServiceUrl, getSessionCookieName, getSessionCookieOptions, hasRegistryServiceUrl, healthPath, isAllowedOrigin, isReservedHandle, isValidHandle, learnCourseDashboardPath, learnCourseLessonPath, learnCoursePath, learnCoursePresentPath, learnCourseStudentsPath, learnDashboardPath, learnHandlePath, linksDashboardPath, linksEditPath, linksHandlePath, marketCheckoutSuccessPath, marketDashboardPath, marketListingEditPath, marketListingPath, marketNewListingPath, marketSellerPath, marketSettingsPath, mediaPath, normalizeHandleInput, notifyPath, notifySettingsPath, payHistoryPath, payPath, payTopupPath, payTopupSuccessPath, privacyPath, profileEditPath, profileLoginPath, profilePath, profileRegisterPath, profileUrl, projectPath, rateLimit, registryDocsPath, registryPath, registryServiceUrl, servicesByTier, servicesByVisibility, standaloneDashboardMiddleware, subscribePath, tier1Headers, tier2Headers, tier3Headers, validateOrigin, whitepaperPath, withCors };
491
+ export { ALLOWED_FRAME_ORIGINS, APP_DISPLAY_NAME, type ForestScopeConfig, HANDLE_ALLOWED_CHARS, HANDLE_ERROR, HANDLE_INPUT_PATTERN, HANDLE_PATTERN, IDENTITY_CATEGORIES, type NodeSelfInfo, RESERVED_HANDLES, SERVICES, SERVICE_NAMES, SESSION_COOKIE_NAME, type ServiceCategory, type ServiceDefinition, type ServiceTier, type ServiceVisibility, type StandaloneDashboardMiddlewareOptions, apiFetch, apiUrl, articleAuthorPath, articlePath, articlesPath, authAgentsPath, authAppsPath, authAttestationsPath, authAuthorizePath, authDeveloperAppPath, authDeveloperAppsPath, authGroupSettingsPath, authGroupsPath, authLoginPath, authMembersPath, authNewGroupPath, authNewStubPath, authNotificationsPath, authOnboardPath, authRegisterPath, authSecurityPath, authSettingsPath, authStubsPath, bugsAdminPath, bugsPath, buildPath, buildPublicUrl, buildPublicUrlAbsolute, buildServiceUrlMap, bumpPath, chatConversationPath, chatConversationsPath, chatPath, coffeeDashboardPath, coffeeEditPath, coffeeHandlePath, coffeeSuccessPath, connectionsInvitePath, connectionsPath, connectionsPodPath, corsHeaders, corsOptions, developerGuidePath, docsPath, dykilCreatePath, dykilDashboardPath, dykilEmbedPath, dykilHandlePath, dykilResultsPath, dykilSurveyPath, eventAdminPath, eventCheckoutSuccessPath, eventEditPath, eventEditUrl, eventMyTicketsPath, eventMyTicketsUrl, eventPath, eventRegisterPath, eventRegisterUrl, eventUrl, eventsAdminListPath, eventsCheckoutSuccessPath, eventsCreatePath, eventsDashboardPath, getClientIP, getForestScopeConfig, getNodeSelf, getPort, getPublicUrl, getService, getServiceUrl, getSessionCookieName, getSessionCookieOptions, hasRegistryServiceUrl, healthPath, isAllowedOrigin, isReservedHandle, isValidHandle, learnCourseDashboardPath, learnCourseLessonPath, learnCoursePath, learnCoursePresentPath, learnCourseStudentsPath, learnDashboardPath, learnHandlePath, linksDashboardPath, linksEditPath, linksHandlePath, marketCheckoutSuccessPath, marketDashboardPath, marketListingEditPath, marketListingPath, marketNewListingPath, marketSellerPath, marketSettingsPath, mediaPath, normalizeHandleInput, notifyPath, notifySettingsPath, payHistoryPath, payPath, payTopupPath, payTopupSuccessPath, privacyPath, profileEditPath, profileLoginPath, profilePath, profileRegisterPath, profileUrl, projectPath, rateLimit, registryDocsPath, registryPath, registryServiceUrl, servicesByTier, servicesByVisibility, standaloneDashboardMiddleware, subscribePath, tier1Headers, tier2Headers, tier3Headers, validateOrigin, whitepaperPath, withCors };
package/dist/index.js CHANGED
@@ -51,17 +51,14 @@ var SERVICES = [
51
51
  { name: "media", label: "Media", icon: "\u{1F4C1}", description: "Files, images, and .fair attribution", devPort: 3e3, prodPort: 7e3, schema: "media", tier: "core", visibility: "authenticated", category: "kernel" },
52
52
  { name: "registry", label: "Registry", icon: "\u{1F4E1}", description: "Service registry and DFOS relay", devPort: 3e3, prodPort: 7e3, schema: "registry", tier: "core", visibility: "public", category: "kernel" },
53
53
  { name: "notify", label: "Notify", icon: "\u{1F514}", description: "Notifications and preferences", devPort: 3e3, prodPort: 7e3, schema: "notify", tier: "core", visibility: "internal", category: "kernel" },
54
- { name: "usage", label: "Usage", icon: "\u{1F4CA}", description: "Inference cost ledger \u2014 incurred, billed, drift, signed rollup", devPort: 3e3, prodPort: 7e3, schema: "usage", tier: "core", visibility: "authenticated", category: "kernel" },
55
- { name: "calendar", label: "Calendar", icon: "\u{1F4C5}", description: "Temporal entries \u2014 availability, meetings, events, and reminders", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "authenticated", category: "kernel" },
54
+ { name: "usage", label: "Usage", icon: "\u{1F4CA}", description: "Inference cost ledger \u2014 incurred, billed, drift, signed rollup", devPort: 3e3, prodPort: 7e3, schema: "usage", tier: "core", visibility: "internal", category: "kernel" },
55
+ { name: "calendar", label: "Calendar", icon: "\u{1F4C5}", description: "Temporal entries \u2014 availability, meetings, events, and reminders", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "internal", category: "kernel" },
56
56
  { name: "jin", label: "Jin", icon: "\u{1F9ED}", description: "Operator dashboard \u2014 signed approvals, proposals, and usage feed", devPort: 3e3, prodPort: 7e3, schema: "operator", tier: "core", visibility: "internal", category: "kernel" },
57
- { name: "google", label: "Google Workspace", icon: "\u{1F4E8}", description: "Gmail/Calendar/Drive/Meet connector \u2014 OAuth2 auth-code, sealed refresh token", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "authenticated", category: "kernel" },
57
+ { name: "google", label: "Google Workspace", icon: "\u{1F4E8}", description: "Gmail/Calendar/Drive/Meet connector \u2014 OAuth2 auth-code, sealed refresh token", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "internal", category: "kernel" },
58
58
  { name: "vault", label: "Vault", icon: "\u{1F510}", description: "Sealed secrets, delegation grants, and vault-minted service credentials", devPort: 3e3, prodPort: 7e3, schema: null, tier: "core", visibility: "internal", category: "kernel" },
59
- // Core apps — separate processes
59
+ // Standalone URL/port contracts for non-nav callers (health probes,
60
+ // buildPublicUrlAbsolute, check-env). Registry placements decide nav.
60
61
  { name: "events", label: "Events", icon: "\u{1F3AB}", description: "Event creation, ticketing, and management", devPort: 3006, prodPort: 7006, schema: "events", tier: "core", visibility: "public", category: "core" },
61
- // Imajin apps
62
- { name: "coffee", label: "Coffee", icon: "\u2615", description: "Tipping and creator support pages", devPort: 3100, prodPort: 7100, schema: "coffee", tier: "imajin", visibility: "creator", category: "creator" },
63
- { name: "dykil", label: "Surveys", icon: "\u{1F4CB}", description: "Surveys and do-you-know-if-I-like polls", devPort: 3101, prodPort: 7101, schema: "dykil", tier: "imajin", visibility: "creator", category: "creator" },
64
- { name: "links", label: "Links", icon: "\u{1F517}", description: "Link-in-bio pages and click tracking", devPort: 3102, prodPort: 7102, schema: "links", tier: "imajin", visibility: "creator", category: "creator" },
65
62
  { name: "learn", label: "Learn", icon: "\u{1F4DA}", description: "Courses, lessons, and learning progress", devPort: 3103, prodPort: 7103, schema: "learn", tier: "imajin", visibility: "public", category: "core" },
66
63
  { name: "market", label: "Market", icon: "\u{1F3EA}", description: "Local commerce \u2014 buy and sell with trust", devPort: 3104, prodPort: 7104, schema: "market", tier: "imajin", visibility: "public", category: "core" },
67
64
  // Meta — project info and external resources surfaced in the launcher
@@ -196,6 +193,25 @@ function tier3Headers() {
196
193
  // src/brand.ts
197
194
  var APP_DISPLAY_NAME = "imajin (\u03B1)";
198
195
 
196
+ // src/identity-categories.ts
197
+ var IDENTITY_CATEGORIES = [
198
+ "caf\xE9",
199
+ "restaurant",
200
+ "shop",
201
+ "venue",
202
+ "studio",
203
+ "bar",
204
+ "gallery",
205
+ "gym",
206
+ "contractor",
207
+ "trades",
208
+ "professional services",
209
+ "health",
210
+ "education",
211
+ "technology",
212
+ "nonprofit"
213
+ ];
214
+
199
215
  // src/session.ts
200
216
  function getSessionCookieName(env) {
201
217
  const resolved = env ?? (typeof process !== "undefined" && (process.env.IMAJIN_ENV === "dev" || process.env.NODE_ENV === "development") ? "dev" : "prod");
@@ -208,8 +224,7 @@ function isLocalhost() {
208
224
  return prefix.includes("localhost");
209
225
  }
210
226
  function isHostScoped() {
211
- if (typeof process === "undefined") return false;
212
- return process.env.SESSION_COOKIE_SCOPE === "host";
227
+ return typeof process === "undefined" || process.env.SESSION_COOKIE_SCOPE !== "domain";
213
228
  }
214
229
  function getSessionCookieOptions(env) {
215
230
  const local = isLocalhost();
@@ -489,6 +504,7 @@ export {
489
504
  HANDLE_ERROR,
490
505
  HANDLE_INPUT_PATTERN,
491
506
  HANDLE_PATTERN,
507
+ IDENTITY_CATEGORIES,
492
508
  RESERVED_HANDLES,
493
509
  SERVICES,
494
510
  SERVICE_NAMES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ima-jin/config",
3
- "version": "0.8.22",
3
+ "version": "0.8.24",
4
4
  "description": "Shared configuration for Imajin services — CORS, service routing, session config, handle validation, and route helpers",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared organization/place category taxonomy.
3
+ * Values are persisted in profile metadata: keep existing spellings stable,
4
+ * especially `café`, and extend this vocabulary rather than individual pickers.
5
+ * This is a suggestion vocabulary, not a validator for historical custom values.
6
+ */
7
+ export const IDENTITY_CATEGORIES = [
8
+ 'café',
9
+ 'restaurant',
10
+ 'shop',
11
+ 'venue',
12
+ 'studio',
13
+ 'bar',
14
+ 'gallery',
15
+ 'gym',
16
+ 'contractor',
17
+ 'trades',
18
+ 'professional services',
19
+ 'health',
20
+ 'education',
21
+ 'technology',
22
+ 'nonprofit',
23
+ ] as const;
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ export { standaloneDashboardMiddleware } from "./dashboard-redirect-middleware";
3
3
  export type { StandaloneDashboardMiddlewareOptions } from "./dashboard-redirect-middleware";
4
4
  export { tier1Headers, tier2Headers, tier3Headers } from './security-headers';
5
5
  export { APP_DISPLAY_NAME } from './brand';
6
+ export { IDENTITY_CATEGORIES } from './identity-categories';
6
7
 
7
8
  export {
8
9
  SERVICES,
package/src/services.ts CHANGED
@@ -56,19 +56,16 @@ export const SERVICES: readonly ServiceDefinition[] = [
56
56
  { name: "media", label: "Media", icon: "📁", description: "Files, images, and .fair attribution", devPort: 3000, prodPort: 7000, schema: "media", tier: "core", visibility: "authenticated", category: "kernel" },
57
57
  { name: "registry", label: "Registry", icon: "📡", description: "Service registry and DFOS relay", devPort: 3000, prodPort: 7000, schema: "registry", tier: "core", visibility: "public", category: "kernel" },
58
58
  { name: "notify", label: "Notify", icon: "🔔", description: "Notifications and preferences", devPort: 3000, prodPort: 7000, schema: "notify", tier: "core", visibility: "internal", category: "kernel" },
59
- { name: "usage", label: "Usage", icon: "📊", description: "Inference cost ledger — incurred, billed, drift, signed rollup", devPort: 3000, prodPort: 7000, schema: "usage", tier: "core", visibility: "authenticated", category: "kernel" },
60
- { name: "calendar", label: "Calendar", icon: "📅", description: "Temporal entries — availability, meetings, events, and reminders", devPort: 3000, prodPort: 7000, schema: null, tier: "core", visibility: "authenticated", category: "kernel" },
59
+ { name: "usage", label: "Usage", icon: "📊", description: "Inference cost ledger — incurred, billed, drift, signed rollup", devPort: 3000, prodPort: 7000, schema: "usage", tier: "core", visibility: "internal", category: "kernel" },
60
+ { name: "calendar", label: "Calendar", icon: "📅", description: "Temporal entries — availability, meetings, events, and reminders", devPort: 3000, prodPort: 7000, schema: null, tier: "core", visibility: "internal", category: "kernel" },
61
61
  { name: "jin", label: "Jin", icon: "🧭", description: "Operator dashboard — signed approvals, proposals, and usage feed", devPort: 3000, prodPort: 7000, schema: "operator", tier: "core", visibility: "internal", category: "kernel" },
62
- { name: "google", label: "Google Workspace", icon: "📨", description: "Gmail/Calendar/Drive/Meet connector — OAuth2 auth-code, sealed refresh token", devPort: 3000, prodPort: 7000, schema: null, tier: "core", visibility: "authenticated", category: "kernel" },
62
+ { name: "google", label: "Google Workspace", icon: "📨", description: "Gmail/Calendar/Drive/Meet connector — OAuth2 auth-code, sealed refresh token", devPort: 3000, prodPort: 7000, schema: null, tier: "core", visibility: "internal", category: "kernel" },
63
63
  { name: "vault", label: "Vault", icon: "🔐", description: "Sealed secrets, delegation grants, and vault-minted service credentials", devPort: 3000, prodPort: 7000, schema: null, tier: "core", visibility: "internal", category: "kernel" },
64
64
 
65
- // Core apps — separate processes
65
+ // Standalone URL/port contracts for non-nav callers (health probes,
66
+ // buildPublicUrlAbsolute, check-env). Registry placements decide nav.
66
67
  { name: "events", label: "Events", icon: "🎫", description: "Event creation, ticketing, and management", devPort: 3006, prodPort: 7006, schema: "events", tier: "core", visibility: "public", category: "core" },
67
68
 
68
- // Imajin apps
69
- { name: "coffee", label: "Coffee", icon: "☕", description: "Tipping and creator support pages", devPort: 3100, prodPort: 7100, schema: "coffee", tier: "imajin", visibility: "creator", category: "creator" },
70
- { name: "dykil", label: "Surveys", icon: "📋", description: "Surveys and do-you-know-if-I-like polls", devPort: 3101, prodPort: 7101, schema: "dykil", tier: "imajin", visibility: "creator", category: "creator" },
71
- { name: "links", label: "Links", icon: "🔗", description: "Link-in-bio pages and click tracking", devPort: 3102, prodPort: 7102, schema: "links", tier: "imajin", visibility: "creator", category: "creator" },
72
69
  { name: "learn", label: "Learn", icon: "📚", description: "Courses, lessons, and learning progress", devPort: 3103, prodPort: 7103, schema: "learn", tier: "imajin", visibility: "public", category: "core" },
73
70
  { name: "market", label: "Market", icon: "🏪", description: "Local commerce — buy and sell with trust", devPort: 3104, prodPort: 7104, schema: "market", tier: "imajin", visibility: "public", category: "core" },
74
71
 
package/src/session.ts CHANGED
@@ -28,37 +28,27 @@ function isLocalhost(): boolean {
28
28
  }
29
29
 
30
30
  /**
31
- * Cookie domain scope (#1069 Phase 1).
31
+ * Cookie domain scope (#1069 Phase 2).
32
32
  *
33
33
  * `SESSION_COOKIE_SCOPE` controls whether the deployed session cookie is a
34
34
  * shared parent-domain cookie or a host-only cookie:
35
- * - unset / "domain" (default): current behavior — `domain: ".imajin.ai"`,
36
- * readable by every `*.imajin.ai` subdomain. Nothing changes unless this
37
- * is explicitly set.
38
- * - "host": omit the `domain` attribute entirely, so the cookie is scoped
39
- * to the exact host that set it and is NOT sent to other subdomains.
40
- * Apps that relied on reading the shared cookie must adopt scoped app
41
- * tokens first (see `requireSessionOrAppToken` in `@ima-jin/auth` and
42
- * `docs/security/cookie-isolation.md`) before this is flipped for real.
43
- *
44
- * This flag is a primitive for the staged rollout described in
45
- * `docs/security/cookie-isolation.md` — flipping it is a separate, later
46
- * phase, not part of shipping the primitive itself.
35
+ * - unset / "host" (default): omit Domain; only the setting host receives it.
36
+ * - "domain": restore the legacy `.imajin.ai` scope for rollback.
37
+ * Unknown values fail narrow. Same-origin path-proxied apps still receive
38
+ * the cookie; see `docs/security/cookie-isolation.md` for the phase 3 gap.
47
39
  */
48
40
  function isHostScoped(): boolean {
49
- if (typeof process === "undefined") return false;
50
- return process.env.SESSION_COOKIE_SCOPE === "host";
41
+ return typeof process === "undefined" || process.env.SESSION_COOKIE_SCOPE !== "domain";
51
42
  }
52
43
 
53
- /** Cookie options for cross-subdomain sessions.
44
+ /** Cookie options for host-only sessions (with explicit domain rollback).
54
45
  * When called with no argument, auto-detects from IMAJIN_ENV (same logic as getSessionCookieName).
55
46
  * Accepts optional "dev" | "prod" override for explicit control.
56
47
  *
57
48
  * Localhost-aware: when SERVICE_PREFIX contains "localhost", uses
58
49
  * settings compatible with HTTP on localhost (no domain, not secure, lax sameSite).
59
50
  *
60
- * See {@link isHostScoped} for the `SESSION_COOKIE_SCOPE=host` opt-in that
61
- * narrows the deployed cookie to host-only instead of `.imajin.ai`.
51
+ * `SESSION_COOKIE_SCOPE=domain` restores the deployed parent-domain cookie.
62
52
  */
63
53
  export function getSessionCookieOptions(env?: "dev" | "prod") {
64
54
  const local = isLocalhost();