Skip to content

Commit ff0b072

Browse files
committed
feat(builder): add a Production tab telling you how to instrument a build
Everything needed to instrument a production build was in the source, so using it meant reading the source. The dialog now says how, with the commands already filled in for this machine: the path comes from SystemConfigOverride rather than being written out a second time, so the two cannot drift, and the date is today's, which is the one that will work. It switches to Windows syntax on Windows. It explains why each step is there as well as what to type - why a root owned folder is what proves an admin allowed it, why the permission expires by itself, and why the app has to start twice before it takes. Knowing that is what stops the second restart looking like a bug.
1 parent 1b9b93d commit ff0b072

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

‎src/phoenix-builder/builder-connect-dialog.html‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ <h1 class="dialog-title">Phoenix Builder MCP</h1>
44
<ul class="nav nav-tabs no-focus" style="margin-bottom: 0;">
55
<li class="active"><a href="#builder-settings" data-toggle="tab">Settings</a></li>
66
<li><a href="#builder-logs" data-toggle="tab">Console Logs</a></li>
7+
<li><a href="#builder-prod" data-toggle="tab">Production</a></li>
78
</ul>
89
</div>
910
<div class="modal-body tab-content">
@@ -61,6 +62,36 @@ <h1 class="dialog-title">Phoenix Builder MCP</h1>
6162
<span style="opacity: 0.5;">No logs captured yet.</span>
6263
</div>
6364
</div>
65+
<div id="builder-prod" class="tab-pane">
66+
<p class="dialog-message">
67+
MCP is off in production builds. To instrument one, a machine admin drops a dated
68+
permission in a root owned folder &mdash; being able to write there is what proves an
69+
admin allowed it. It is a date, not a switch, so a permission cannot be left on by
70+
accident: it works on that day only.
71+
</p>
72+
73+
<p style="font-weight: bold; margin-bottom: 4px;">1. Grant it (click to copy, then run in a terminal)</p>
74+
<pre class="builder-config-code" style="padding: 8px; border: 1px solid var(--item-border-color); border-radius: 4px; overflow-x: auto; font-size: 12px; cursor: pointer; white-space: pre-wrap; word-break: break-all;" title="Click to copy">{{mcpGrantCommand}}</pre>
75+
<p style="font-size: 12px; opacity: 0.7; margin-top: 4px;">
76+
Writes <code>{{mcpOverrideFile}}</code> with today's date, <code>{{mcpToday}}</code>.
77+
Re-run it on any day you want to instrument again.
78+
</p>
79+
80+
<p style="font-weight: bold; margin-bottom: 4px; margin-top: 12px;">2. Restart the production app twice</p>
81+
<p style="font-size: 12px; opacity: 0.7; margin-top: 0;">
82+
Nothing else to switch on &mdash; the file is the permission, and the app picks it up
83+
by itself. Boot reads no files, to keep startup quick, so it consults a cached copy of
84+
the date: the first start after step 1 caches it, the second acts on it. Removing the
85+
file clears the cache the same way, one start later.
86+
</p>
87+
88+
<p style="font-weight: bold; margin-bottom: 4px; margin-top: 12px;">Revoking</p>
89+
<pre class="builder-config-code" style="padding: 8px; border: 1px solid var(--item-border-color); border-radius: 4px; overflow-x: auto; font-size: 12px; cursor: pointer; white-space: pre-wrap; word-break: break-all;" title="Click to copy">{{mcpRevokeCommand}}</pre>
90+
<p style="font-size: 12px; opacity: 0.7; margin-top: 4px;">
91+
It also lapses on its own at midnight. While anything is connected the production
92+
window shows a red <b>Remote Controlled</b> badge in its status bar.
93+
</p>
94+
</div>
6495
</div>
6596
<div class="modal-footer">
6697
<button class="dialog-button btn primary" data-button-id="ok">Done</button>

‎src/phoenix-builder/main.js‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,34 @@ define(function (require, exports, module) {
179179
let url = localStorage.getItem("phoenixBuilderWsUrl") || DEFAULT_WS_URL,
180180
enabled = localStorage.getItem("phoenixBuilderEnabled") === "true";
181181

182+
// Ready to run, so the Production tab needs nothing looked up elsewhere.
183+
// The path comes from SystemConfigOverride rather than being written out
184+
// again here, so the two cannot drift apart.
185+
const overrideFile = Phoenix.fs.getTauriPlatformPath(SystemConfigOverride.OVERRIDE_FILE_PATH);
186+
const overrideDir = overrideFile.replace(/[/\\][^/\\]+$/, "");
187+
const now = new Date();
188+
const today = now.getFullYear() + "-" +
189+
String(now.getMonth() + 1).padStart(2, "0") + "-" +
190+
String(now.getDate()).padStart(2, "0");
191+
const isWin = Phoenix.platform === "win";
192+
const grantCommand = isWin
193+
? 'mkdir "' + overrideDir + '" & echo {"' + PROD_OVERRIDE_DATE_KEY + '": "' + today +
194+
'"} > "' + overrideFile + '"'
195+
: 'sudo mkdir -p "' + overrideDir + '" && echo \'{"' + PROD_OVERRIDE_DATE_KEY +
196+
'": "' + today + '"}\' | sudo tee "' + overrideFile + '"';
197+
const revokeCommand = isWin
198+
? 'del "' + overrideFile + '"'
199+
: 'sudo rm "' + overrideFile + '"';
200+
182201
const templateVars = {
183202
url: url,
184203
enabled: enabled,
185204
connected: PhoenixBuilderClient.isConnected(),
186-
instanceName: PhoenixBuilderClient.getInstanceName()
205+
instanceName: PhoenixBuilderClient.getInstanceName(),
206+
mcpOverrideFile: overrideFile,
207+
mcpToday: today,
208+
mcpGrantCommand: grantCommand,
209+
mcpRevokeCommand: revokeCommand
187210
};
188211

189212
const template = Mustache.render(BuilderConnectTemplate, templateVars);

0 commit comments

Comments
 (0)