mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-19 09:45:07 +00:00
feat+docs+release(v0.4.3): D76 — README install-path overhaul + OLP_BIND env + AI-install prompt + ADR 0011 amendment (#48)
10 README install gaps catalogued and fixed in one D-day after v0.4.2's PI231 E2E session exposed that the v0.4.0-v0.4.2 README Quick Start was fictional (npm package isn't published; olp setup/start commands don't exist). F5 (OLP_BIND env) ships in the same patch so the documented LAN onboarding flow actually works. AI-driven install prompt added per Phase 4 charter brainstorm Top-5 inheritance candidate #2 (D64-D67 built the doctor framework; D76 closes the README half). ## G1-G7: README Quick Start now real Rewrote § "Manual install" from placeholder text to the empirically-verified sequence: - Prerequisites (Node >= 18 + provider CLI install matrix) - git clone + npm test verify - olp-keys keygen --owner FIRST (allow_anonymous=false default needs a key) - Per-provider OAuth (claude setup-token / codex login --device-auth / MISTRAL_API_KEY) - ~/.olp/config.json with the minimum that actually serves traffic - npm start - Smoke-test via curl + olp doctor - IDE pointing ## G8 / F5: OLP_BIND env shipped server.mjs: - const BIND = process.env.OLP_BIND ?? '127.0.0.1' (safe default unchanged) - server.listen(PORT, BIND, ...) replaces hard-coded '127.0.0.1' - New startup warn anonymous_key_advertised_with_lan_bind fires when OLP_BIND is non-loopback AND auth.advertise_anonymous_key: true (operator visibility into trust-context overlap) Pre-D76 the server only accepted loopback connections, so the documented olp-connect <ip> family-onboarding flow was unreachable from LAN without SSH tunneling. F5 makes ADR 0011 operational instead of aspirational. ## G10: AI-driven install prompt README § "Install with your AI (the fast path)" — verbatim prompt the operator pastes into Claude Code / Cursor / Copilot / Aider. The AI follows README + uses olp doctor --json next_action.ai_executable[] for self-repair, stopping only when human_required[] is non-empty (provider OAuth dances). Closes the Phase 4 brainstorm #2 inheritance candidate. ## Opening compressed § "Why OLP" (3 paragraphs of Anthropic 2026-06-15 billing history) removed from the top. The OCP-trigger context moved to § "Migration from OCP" at the bottom, condensed into a single paragraph. New users land on value-prop + § "What you get" + install paths without needing to digest 2026-05-14 billing history first. OCP users get a one-line pointer at the top. ## Configuration + Env Variables sections updated - § Configuration: placeholder replaced with full ~/.olp/config.json schema documentation, every field cross-referenced to its ADR - § Environment Variables: added OLP_BIND, OLP_API_KEY, OLP_OWNER_TOKEN, OLP_PROXY_URL rows that were used in the manual-install flow but previously undocumented ## ADR 0011 § Deployment configurations amendment Codifies the three deployment trust contexts: - 127.0.0.1 (loopback only) — safe with any auth posture - RFC1918 / tailnet / specific LAN IP — anonymous_key OK (the documented trusted-LAN zero-config family onboarding flow) - Public IP — incompatible with advertise_anonymous_key: true Documents the new anonymous_key_advertised_with_lan_bind startup warn event. Closes ADR 0011's pre-D76 dangling reference to a non-existent BIND_ADDRESS concept. ## Test count 714 (v0.4.2) -> 717 (v0.4.3). +3 D76 regression tests in Suite 36 (36s/36t/36u) pinning OLP_BIND wiring + safety warn + ADR amendment. ## Process learning Every D-day reviewer rubric should add "open README §-Quick-Start and verify the commands literally exist + work in the current repo" — would have caught G1-G7 at v0.4.0 close. Combined with D74 (review-against-spec) + D75 (review-without-deployment), D76 (review-without-following-README) codifies the third tier of review discipline. ## Out of D76 scope (deferred) - F6 (doctor client-side vs server-side check separation) — needs design ADR for --remote mode. Phase 5. - D75 reviewer P2-1 (ADR 0004 per-hop schema amendment) + P2-2 (defensive typeof hopModel === 'string') — both genuine follow-ups, neither blocking. - scripts/migrate-from-ocp.mjs — Phase 7. Co-authored-by: dtzp555 <dtzp555@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+30
-1
@@ -18,6 +18,14 @@
|
||||
* so OLP can co-host with OCP for migration windows. ADR 0010 §
|
||||
* Default port. Set OLP_PORT=3456 explicitly to restore the
|
||||
* pre-D60 default when not co-hosting with OCP.)
|
||||
* OLP_BIND — listen address (default: 127.0.0.1 since D76 / v0.4.3). Set
|
||||
* to 0.0.0.0 (or a specific interface IP) to accept connections
|
||||
* from LAN clients (required for olp-connect <ip> to actually
|
||||
* reach the server). Server emits a startup warn if BIND
|
||||
* resolves to a non-loopback address AND auth.allow_anonymous
|
||||
* is true (anonymous-key over LAN may be acceptable; anonymous-
|
||||
* key over public internet is not — see ADR 0011 § Deployment
|
||||
* configurations).
|
||||
*/
|
||||
|
||||
import { createServer } from 'node:http';
|
||||
@@ -77,6 +85,14 @@ const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
|
||||
const VERSION = pkg.version;
|
||||
|
||||
const PORT = parseInt(process.env.OLP_PORT ?? '4567', 10);
|
||||
// F5 / D76: OLP_BIND env. Defaults to 127.0.0.1 (loopback only — secure
|
||||
// default). Operators expose LAN by setting OLP_BIND=0.0.0.0 (or a specific
|
||||
// interface). Per ADR 0011 § Deployment configurations:
|
||||
// - 127.0.0.1: trusted single-machine; safe with any auth posture
|
||||
// - RFC1918 / tailnet / specific LAN IP: trusted-LAN — anonymous_key OK
|
||||
// - 0.0.0.0: ALL interfaces — operator MUST ensure auth posture matches the
|
||||
// network reachability (e.g. no advertise_anonymous_key on public IP)
|
||||
const BIND = process.env.OLP_BIND ?? '127.0.0.1';
|
||||
const BODY_LIMIT = 5 * 1024 * 1024; // 5 MB
|
||||
|
||||
// ── Logging ───────────────────────────────────────────────────────────────
|
||||
@@ -253,6 +269,19 @@ if (_authConfig.advertise_anonymous_key === true) {
|
||||
message: 'auth.advertise_anonymous_key=true but no active key with plaintext_advertise exists. Run `olp-keys keygen --anonymous --advertise` to create one. /health.anonymousKey will NOT be emitted until then. See ADR 0011.',
|
||||
});
|
||||
}
|
||||
// F5 / D76 (ADR 0011 Deployment configurations): publishing the anonymous
|
||||
// key via /health is only safe when /health is reachable ONLY from a
|
||||
// trusted network. If OLP_BIND is set to a non-loopback address AND
|
||||
// advertise_anonymous_key is true, warn the operator. We can't tell from
|
||||
// here whether the non-loopback bind is "trusted LAN" (RFC1918 / tailnet)
|
||||
// or "public internet" — that's the operator's responsibility. The warn is
|
||||
// a checkpoint, not a hard gate.
|
||||
if (BIND !== '127.0.0.1' && BIND !== 'localhost' && BIND !== '::1') {
|
||||
logEvent('warn', 'anonymous_key_advertised_with_lan_bind', {
|
||||
message: `auth.advertise_anonymous_key=true with OLP_BIND=${BIND} — /health.anonymousKey will be reachable from any host that can connect to ${BIND}:${PORT}. Confirm this address is on a trusted LAN (RFC1918 / tailnet) — never a public IP. See ADR 0011 § Deployment configurations.`,
|
||||
bind: BIND,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal — test seam: inject a synthetic auth config (no file I/O). */
|
||||
@@ -2258,7 +2287,7 @@ const isMain = (() => {
|
||||
|
||||
if (isMain) {
|
||||
const server = createOlpServer();
|
||||
server.listen(PORT, '127.0.0.1', () => {
|
||||
server.listen(PORT, BIND, () => {
|
||||
const enabledCount = loadedProviders.size;
|
||||
// D74 P3-5: banner no longer hardcodes the phase. Derives from VERSION
|
||||
// (which advances at every Phase close) so banner stays accurate
|
||||
|
||||
Reference in New Issue
Block a user