@fonderie/cli 0.4.0 → 0.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/bin/fonderie.mjs CHANGED
@@ -328,6 +328,7 @@ const ADMIN_PAGES = {
328
328
  routes: { path: '/routes', about: 'every exposed route with its guard' },
329
329
  tokens: { path: '/access/tokens', about: 'the admin token verdict + legacy per-brick tokens' },
330
330
  log: { path: '/activity/admin-log', about: 'who did what through the surface (--limit, --before)' },
331
+ user: { path: '/users', about: 'look up a user: admin user <email|id> [sessions|history|revoke-sessions|suspend|unsuspend]' },
331
332
  };
332
333
  async function adminCmd() {
333
334
  const pageName = argv[1];
@@ -338,6 +339,20 @@ async function adminCmd() {
338
339
  process.exit(2);
339
340
  }
340
341
  const prefix = (process.env.FONDERIE_ADMIN_PREFIX || '/_admin').replace(/\/$/, '');
342
+ if (pageName === 'user') {
343
+ // fonderie admin user <email|id> [sessions|history|revoke-sessions|suspend|unsuspend]
344
+ const who = argv[2]; const verb = argv[3] ?? 'show';
345
+ if (!who) { console.error('fonderie admin user <email|id> [sessions|history|revoke-sessions|suspend|unsuspend]'); process.exit(2); }
346
+ const byEmail = who.includes('@');
347
+ const base = byEmail ? `${prefix}/users?email=${encodeURIComponent(who)}` : `${prefix}/users/${encodeURIComponent(who)}`;
348
+ if (verb === 'show') return adminFetch('GET', base);
349
+ if (byEmail) { console.error('sessions/history/revoke-sessions/suspend/unsuspend need the user id (run `admin user <email>` first).'); process.exit(2); }
350
+ const sub = { sessions: ['GET', '/sessions'], history: ['GET', '/login-history'], 'revoke-sessions': ['DELETE', '/sessions'], suspend: ['POST', '/suspend'], unsuspend: ['POST', '/unsuspend'] }[verb];
351
+ if (!sub) { console.error(`unknown verb "${verb}"`); process.exit(2); }
352
+ const q = new URLSearchParams(); const limit = arg('--limit', undefined); if (limit && verb === 'history') q.set('limit', limit);
353
+ const qs = q.toString();
354
+ return adminFetch(sub[0], base + sub[1] + (qs ? `?${qs}` : ''));
355
+ }
341
356
  const q = new URLSearchParams();
342
357
  const limit = arg('--limit', undefined);
343
358
  const before = arg('--before', undefined);
@@ -443,6 +458,7 @@ else {
443
458
  fonderie template <get|set|delete|history|rollback> [type] [text] [--locale <l>] [--subject <s>] [--html <h>] ...
444
459
  manage a live deployment over its admin API — set FONDERIE_ADMIN_URL + FONDERIE_ADMIN_TOKEN
445
460
  fonderie admin <attention|manifest|doctor|config|routes|tokens|log> [--limit <n>] [--before <cursor>]
461
+ fonderie admin user <email|id> [sessions|history|revoke-sessions|suspend|unsuspend]
446
462
  read a deployment's operator surface (@fonderie/admin) — same env; FONDERIE_ADMIN_PREFIX if moved
447
463
 
448
464
  Zero deps. No MCP server. A binary + markdown that runs in any agent harness.`);
@@ -141,6 +141,15 @@ await (async () => {
141
141
  if (!find('GET', '/_admin')) fail('admin attention: should hit the prefix root');
142
142
  if (!find('GET', '/_admin/activity/admin-log?limit=5&before=abc')) fail('admin log: flags not forwarded');
143
143
  if (!find('GET', '/ops/doctor')) fail('admin doctor: FONDERIE_ADMIN_PREFIX not honoured');
144
+ await cli(['admin', 'user', 'ada@example.com']);
145
+ await cli(['admin', 'user', 'u1', 'history', '--limit', '3']);
146
+ await cli(['admin', 'user', 'u1', 'suspend']);
147
+ if (!find('GET', '/_admin/users?email=ada%40example.com')) fail('admin user <email>: wrong lookup path');
148
+ if (!find('GET', '/_admin/users/u1/login-history?limit=3')) fail('admin user history: flags not forwarded');
149
+ if (!find('POST', '/_admin/users/u1/suspend')) fail('admin user suspend: wrong request');
150
+ let needsId = 0;
151
+ try { await cli(['admin', 'user', 'ada@example.com', 'suspend']); } catch (e) { needsId = e.code; }
152
+ if (needsId !== 2) fail(`admin user <email> suspend should exit 2, got ${needsId}`);
144
153
  let unknown = 0;
145
154
  try { await cli(['admin', 'nope']); } catch (e) { unknown = e.code; }
146
155
  if (unknown !== 2) fail(`admin <unknown page> should exit 2, got ${unknown}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonderie/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "The Fonderie CLI — teaches any coding agent the SDK without loading it eagerly. `fonderie skill` writes a lazy skill (a small router + per-package bodies read on demand); `fonderie query` answers what to install for a capability. Zero deps, runs anywhere.",
5
5
  "keywords": [
6
6
  "fonderiejs",