@venturewild/workspace 0.3.0 → 0.3.1

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": "@venturewild/workspace",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Claude Code Web — Replit/Lovable-style chat-first browser UI that wraps the AI agent already installed on your machine.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -36,7 +36,15 @@ import { ActivityBus } from './activity.mjs';
36
36
  import { loadIdentity, saveIdentity, markOnboarded, TONES } from './agent-identity.mjs';
37
37
  import { probeAgentReadiness } from './agent-readiness.mjs';
38
38
  import { AutoUpdater, npmInstall, recordUpdate, loadUpdateSettings, PACKAGE_NAME } from './auto-update.mjs';
39
- import { consentStatus, revokeConsent, readAudit, OPERATE_TIER } from './support-consent.mjs';
39
+ import {
40
+ consentStatus,
41
+ revokeConsent,
42
+ readAudit,
43
+ grantConsent,
44
+ OPERATE_TIER,
45
+ MAX_TIER,
46
+ MAX_GRANT_MINUTES,
47
+ } from './support-consent.mjs';
40
48
  import { ClaudeLoginSession } from './agent-login.mjs';
41
49
  import { ErrorReporter } from './error-reporter.mjs';
42
50
  import { DaemonBridge } from './daemon.mjs';
@@ -1081,6 +1089,10 @@ export async function createServer(overrides = {}) {
1081
1089
  remainingMs: s.remainingMs,
1082
1090
  active,
1083
1091
  operate,
1092
+ // Whether THIS viewer may grant/revoke (owner only) — drives the banner's
1093
+ // one-tap "Allow VentureWild support" control so consent is never a CLI paste.
1094
+ canGrant: Boolean(ROLE_CAPABILITIES[c.get('role')]?.chatWrite),
1095
+ maxTier: MAX_TIER,
1084
1096
  lastAction: last ? { action: last.action, ts: last.ts, ok: last.ok } : null,
1085
1097
  });
1086
1098
  });
@@ -1092,6 +1104,31 @@ export async function createServer(overrides = {}) {
1092
1104
  return c.json({ audit: readAudit(globalDir(), { limit }) });
1093
1105
  });
1094
1106
 
1107
+ // Phase 4 (Pillar E): the owner grants time-boxed support consent with a UI tap —
1108
+ // so "yes, VentureWild may help" is a browser click, never a terminal paste (the
1109
+ // CLI `support allow` still works too). Owner-only. Operate tiers (3/4) require an
1110
+ // explicit confirmOperate so a stray tap can't hand over agent/shell control.
1111
+ app.post('/api/support/grant', async (c) => {
1112
+ const forbidden = require(c, 'chatWrite');
1113
+ if (forbidden) return forbidden;
1114
+ let body;
1115
+ try {
1116
+ body = await c.req.json();
1117
+ } catch {
1118
+ body = {};
1119
+ }
1120
+ const tier = Math.min(MAX_TIER, Math.max(1, Math.floor(Number(body.tier) || 1)));
1121
+ const minutes = Math.min(MAX_GRANT_MINUTES, Math.max(1, Math.floor(Number(body.minutes) || 30)));
1122
+ if (tier >= OPERATE_TIER && body.confirmOperate !== true) {
1123
+ return c.json({ error: 'operate-confirm-required', tier }, 400);
1124
+ }
1125
+ const rec = grantConsent(globalDir(), { tier, minutes });
1126
+ if (!rec) return c.json({ error: 'write-failed' }, 500);
1127
+ appendLine('operator', `support consent granted via UI tier=${rec.tier} minutes=${minutes}`);
1128
+ activityBus.publish({ type: 'support-granted', tier: rec.tier, at: Date.now() });
1129
+ return c.json({ granted: true, tier: rec.tier, expiresAt: rec.expiresAt });
1130
+ });
1131
+
1095
1132
  app.post('/api/support/revoke', (c) => {
1096
1133
  const forbidden = require(c, 'chatWrite');
1097
1134
  if (forbidden) return forbidden;