@almadar/orb 3.4.0 → 3.5.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/orb",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "description": "Orb CLI - deterministic when it can be, intelligent when it needs to be",
5
5
  "license": "BSL-1.1",
6
6
  "repository": {
@@ -49,10 +49,10 @@
49
49
  "node": ">=16.0.0"
50
50
  },
51
51
  "optionalDependencies": {
52
- "@almadar/orb-darwin-x64": "3.4.0",
53
- "@almadar/orb-darwin-arm64": "3.4.0",
54
- "@almadar/orb-linux-x64": "3.4.0",
55
- "@almadar/orb-linux-arm64": "3.4.0",
56
- "@almadar/orb-windows-x64": "3.4.0"
52
+ "@almadar/orb-darwin-x64": "3.5.0",
53
+ "@almadar/orb-darwin-arm64": "3.5.0",
54
+ "@almadar/orb-linux-x64": "3.5.0",
55
+ "@almadar/orb-linux-arm64": "3.5.0",
56
+ "@almadar/orb-windows-x64": "3.5.0"
57
57
  }
58
58
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/shell",
3
- "version": "2.64.0",
3
+ "version": "2.78.0",
4
4
  "private": false,
5
5
  "description": "Minimal full-stack shell template for Almadar applications",
6
6
  "packageManager": "pnpm@10.30.3",
@@ -13,12 +13,12 @@
13
13
  "test:watch": "vitest"
14
14
  },
15
15
  "dependencies": {
16
- "@almadar/core": "^10.57.0",
17
- "@almadar/evaluator": "^2.40.0",
16
+ "@almadar/core": "^10.69.0",
17
+ "@almadar/evaluator": "^2.42.0",
18
18
  "@almadar/logger": "^1.11.0",
19
19
  "@almadar/patterns": "^2.101.0",
20
20
  "@almadar/syntax": "^1.15.0",
21
- "@almadar/ui": "^5.147.0",
21
+ "@almadar/ui": "^5.159.0",
22
22
  "@monaco-editor/react": "^4.7.0",
23
23
  "@react-three/drei": "^9.92.0",
24
24
  "@react-three/fiber": "^9.0.0",
@@ -13,12 +13,12 @@
13
13
  "test:watch": "vitest"
14
14
  },
15
15
  "dependencies": {
16
- "@almadar/core": "^10.57.0",
17
- "@almadar/evaluator": "^2.40.0",
18
- "@almadar/integrations": "^2.23.0",
16
+ "@almadar/core": "^10.69.0",
17
+ "@almadar/evaluator": "^2.42.0",
18
+ "@almadar/integrations": "^2.27.0",
19
19
  "@almadar/logger": "^1.11.0",
20
- "@almadar/runtime": "^6.53.0",
21
- "@almadar/server": "^2.34.0",
20
+ "@almadar/runtime": "^6.60.0",
21
+ "@almadar/server": "^2.38.0",
22
22
  "cors": "^2.8.5",
23
23
  "dotenv": "^16.4.7",
24
24
  "express": "^4.21.2",
@@ -13,7 +13,14 @@ import {
13
13
  notFoundHandler,
14
14
  debugEventsRouter,
15
15
  personasRouter,
16
+ pushRouter,
17
+ pushServiceWorkerHandler,
18
+ PUSH_SERVICE_WORKER_PATH,
19
+ reportsRouter,
20
+ createHooksRouter,
16
21
  } from '@almadar/server';
22
+ import { hookProviders } from './hooks-providers.js';
23
+ import { broadcastBusEvent } from './sse.js';
17
24
  import { registerRoutes } from './routes.js';
18
25
 
19
26
  export const app: Express = express();
@@ -24,7 +31,12 @@ app.use(helmet());
24
31
  app.use(cors({ origin: env.CORS_ORIGIN, credentials: true }));
25
32
  app.use(express.json({ limit: '1mb' }));
26
33
  app.use(express.urlencoded({ extended: true, limit: '1mb' }));
27
- app.use('/api', rateLimit({ windowMs: 15 * 60 * 1000, max: 300, standardHeaders: true, legacyHeaders: false }));
34
+ // Rate limiting protects deployed apps; verification walkers and local dev
35
+ // fire hundreds of bridge events per minute and must not be throttled —
36
+ // ORB_DISABLE_RATE_LIMIT=1 (set by the verify harness) bypasses it.
37
+ if (process.env.ORB_DISABLE_RATE_LIMIT !== '1') {
38
+ app.use('/api', rateLimit({ windowMs: 15 * 60 * 1000, max: 300, standardHeaders: true, legacyHeaders: false }));
39
+ }
28
40
 
29
41
  // Health check
30
42
  app.get('/health', (_req, res) => {
@@ -34,6 +46,34 @@ app.get('/health', (_req, res) => {
34
46
  // Debug event bus endpoints (dev-only, no-op in production)
35
47
  app.use('/api/debug', debugEventsRouter());
36
48
 
49
+ // Web Push surface (browser/push-subscribe): public VAPID key + the shared
50
+ // service worker (root-scoped — a SW's max scope is its own directory).
51
+ app.use('/api/push', pushRouter);
52
+ app.get(PUSH_SERVICE_WORKER_PATH, pushServiceWorkerHandler);
53
+
54
+ // Inbound webhook ingress (I-19 decision): mounted BEFORE the authenticated
55
+ // /api routes — hook senders (Google Calendar watch channels, e-sign status,
56
+ // banking callbacks) cannot present a Firebase token, so each provider
57
+ // VERIFIES its own signature/channel token and unverified requests get 400.
58
+ // Providers are DERIVED from this app's invoked services (generated
59
+ // hooks-providers.ts, I-26). Dispatch = SSE bus broadcast to every connected
60
+ // client, so client circuits' `listens` fire; cron pull stays the backstop.
61
+ app.use(
62
+ '/api/hooks',
63
+ createHooksRouter({
64
+ providers: hookProviders(),
65
+ dispatch: (event, payload) => {
66
+ broadcastBusEvent(undefined, {
67
+ type: 'bus',
68
+ event,
69
+ payload,
70
+ source: { orbital: 'webhook', trait: 'ingress' },
71
+ timestamp: Date.now(),
72
+ });
73
+ },
74
+ }),
75
+ );
76
+
37
77
  // Dev persona roster (no-op unless ALLOW_DEV_AUTH_BYPASS). Mounted BEFORE
38
78
  // registerRoutes, which applies authenticateFirebase to /api — a pre-login
39
79
  // persona picker cannot present a token it does not have yet.
@@ -42,6 +82,10 @@ app.use('/api', personasRouter());
42
82
  // Register generated routes
43
83
  registerRoutes(app);
44
84
 
85
+ // Server-side report export (Excel/PDF/CSV). Mounted AFTER registerRoutes so
86
+ // the /api auth middleware it registers covers this route too.
87
+ app.use('/api/reports', reportsRouter);
88
+
45
89
  // Error handling
46
90
  app.use(notFoundHandler);
47
91
  app.use(errorHandler);
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Hook Providers
3
+ *
4
+ * Checked-in stub so the template builds standalone in CI; the compiler
5
+ * overwrites it with the provider map derived from the app's invoked
6
+ * services × the registry's hook declarations (I-26).
7
+ */
8
+
9
+ export function hookProviders() {
10
+ return {};
11
+ }
@@ -21,11 +21,36 @@ try {
21
21
  logger.warn(`Firebase not configured — auth/db routes disabled: ${message}`);
22
22
  }
23
23
 
24
+ import { validateIntegrationEnv, FirestoreCredentialPersistence } from '@almadar/server';
24
25
  import { app } from './app.js';
26
+ import { invokedServices, installTenantCredentialStore } from './services/clients.js';
27
+
28
+ // Fail fast in production when a required integration credential is missing
29
+ // (see SECRETS.md); registers the invoked services for /health reporting.
30
+ validateIntegrationEnv(invokedServices);
25
31
 
26
32
  const PORT = env.PORT || 3030;
27
33
 
28
34
  async function start(): Promise<void> {
35
+ // W4 tenant credential store: with a master key configured, stored
36
+ // credentials (Firestore rows, AES-256-GCM) layer over the env —
37
+ // store → env → unconfigured — and go live on change without restart.
38
+ if (process.env.ALMADAR_CREDENTIAL_MASTER_KEY) {
39
+ try {
40
+ await installTenantCredentialStore(new FirestoreCredentialPersistence());
41
+ logger.info('Tenant credential store installed');
42
+ } catch (e) {
43
+ const message = e instanceof Error ? e.message : String(e);
44
+ // A configured master key IS the deployment's statement that the store
45
+ // is in use — failing to serve it in production is a boot failure.
46
+ if (env.NODE_ENV === 'production') {
47
+ logger.error(`Tenant credential store failed to initialize — refusing to start: ${message}`);
48
+ throw e;
49
+ }
50
+ logger.warn(`Tenant credential store unavailable — falling back to env credentials: ${message}`);
51
+ }
52
+ }
53
+
29
54
  // Seed mock data when USE_MOCK_DATA is enabled
30
55
  if (env.USE_MOCK_DATA) {
31
56
  try {
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Service Clients — placeholder
3
+ *
4
+ * Compiler generates the real service clients here (delegating to
5
+ * @almadar/integrations; see orbital-shell-typescript codegen/service.rs).
6
+ * This stub only lets the template build standalone; an emitted app
7
+ * overwrites it wholesale.
8
+ */
9
+
10
+ export const declaredServices = [] as const;
11
+
12
+ export const invokedServices = [] as const;
13
+
14
+ /** Overwritten at emit time with the RuntimeIntegrationManager-backed store install. */
15
+ export async function installTenantCredentialStore(_adapter: object): Promise<void> {
16
+ // {{GENERATED_SERVICE_CLIENTS}}
17
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Live-push SSE channel — placeholder
3
+ *
4
+ * Compiler generates the real SSE module here (connection registry +
5
+ * cross-client broadcast; see orbital-shell-typescript backend/server/sse.rs).
6
+ * This stub only lets the template build standalone; an emitted app
7
+ * overwrites it wholesale.
8
+ */
9
+
10
+ export interface BusBroadcastItem {
11
+ type: 'bus';
12
+ event: string;
13
+ payload?: object;
14
+ source: { orbital: string; trait: string };
15
+ timestamp: number;
16
+ }
17
+
18
+ export function broadcastBusEvent(_originClientId: string | undefined, _item: BusBroadcastItem): void {
19
+ // {{GENERATED_SSE_BROADCAST}}
20
+ }
@@ -5,7 +5,7 @@
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
7
7
  "dependencies": {
8
- "@almadar/core": "^10.57.0",
8
+ "@almadar/core": "^10.69.0",
9
9
  "zod": "^3.22.0"
10
10
  }
11
11
  }