loki-mode 7.14.0 → 7.15.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/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/loki +181 -5
- package/dashboard/__init__.py +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/OPEN-CORE-BOUNDARY.md +58 -0
- package/docs/R9-OPEN-CORE-HOOKS-PLAN.md +113 -0
- package/loki-ts/dist/loki.js +229 -209
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Autonomous spec-to-product system. Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product via the RARV-C closure loop, with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v7.
|
|
6
|
+
# Loki Mode v7.15.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -383,4 +383,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
383
383
|
|
|
384
384
|
---
|
|
385
385
|
|
|
386
|
-
**v7.
|
|
386
|
+
**v7.15.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.15.0
|
package/autonomy/loki
CHANGED
|
@@ -25275,6 +25275,173 @@ _loki_gist_upload() {
|
|
|
25275
25275
|
echo -e "${GREEN}Shared: ${gist_url}${NC}"
|
|
25276
25276
|
}
|
|
25277
25277
|
|
|
25278
|
+
# loki_tier_gate - R9 open-core tier/license seam.
|
|
25279
|
+
#
|
|
25280
|
+
# OSS-FIRST CONTRACT: this is a no-op ALLOW for OSS users. LOKI_TIER defaults
|
|
25281
|
+
# to "oss" and every existing free feature stays fully free. This function is
|
|
25282
|
+
# the single place where a future hosted/enterprise build would gate a
|
|
25283
|
+
# hosted-only capability. It is NEVER called from any existing free command
|
|
25284
|
+
# path; its only caller is the opt-in --hosted publish seam below. For OSS
|
|
25285
|
+
# (the default), it always returns 0 (allow).
|
|
25286
|
+
#
|
|
25287
|
+
# Args: $1 = capability name (informational; e.g. "hosted_publish").
|
|
25288
|
+
# Returns: 0 = allowed, 1 = gated (non-OSS tier without entitlement).
|
|
25289
|
+
# Env: LOKI_TIER (default "oss"), LOKI_LICENSE_KEY (optional, non-OSS only).
|
|
25290
|
+
loki_tier_gate() {
|
|
25291
|
+
local capability="${1:-}"
|
|
25292
|
+
local tier="${LOKI_TIER:-oss}"
|
|
25293
|
+
|
|
25294
|
+
# OSS tier: everything is allowed, always. No license, no network, no gate.
|
|
25295
|
+
if [ "$tier" = "oss" ]; then
|
|
25296
|
+
return 0
|
|
25297
|
+
fi
|
|
25298
|
+
|
|
25299
|
+
# Non-OSS tiers (hosted/enterprise) are a SEAM only. The hosted backend
|
|
25300
|
+
# and license-verification service do not exist yet, so we cannot validate
|
|
25301
|
+
# an entitlement. Be honest: do not pretend to grant a paid capability.
|
|
25302
|
+
# A real hosted build replaces this branch with a verified license check.
|
|
25303
|
+
if [ -z "${LOKI_LICENSE_KEY:-}" ]; then
|
|
25304
|
+
echo -e "${YELLOW}LOKI_TIER='${tier}' requested but no LOKI_LICENSE_KEY set.${NC}" >&2
|
|
25305
|
+
echo "Hosted/enterprise license verification is not available yet." >&2
|
|
25306
|
+
echo "OSS users: leave LOKI_TIER unset (or 'oss') -- everything stays free." >&2
|
|
25307
|
+
return 1
|
|
25308
|
+
fi
|
|
25309
|
+
|
|
25310
|
+
# A license key is present but there is no verification backend yet. We do
|
|
25311
|
+
# NOT fabricate a successful verification. The capability stays ungated for
|
|
25312
|
+
# OSS-equivalent use; the seam is documented in docs/OPEN-CORE-BOUNDARY.md.
|
|
25313
|
+
echo -e "${YELLOW}LOKI_LICENSE_KEY set but the verification backend is not available yet (R9 seam).${NC}" >&2
|
|
25314
|
+
return 0
|
|
25315
|
+
}
|
|
25316
|
+
|
|
25317
|
+
# _loki_hosted_publish_proof - R9 hosted proof-publish client stub.
|
|
25318
|
+
#
|
|
25319
|
+
# Posts an ALREADY-REDACTED proof page to a self-hosted/SaaS endpoint given by
|
|
25320
|
+
# LOKI_HOSTED_ENDPOINT. There is NO official Loki hosted backend yet; this is a
|
|
25321
|
+
# clean client seam an operator can point at their own endpoint. We never
|
|
25322
|
+
# fabricate a hosted URL: on success we print the URL the endpoint returned (or
|
|
25323
|
+
# the endpoint itself); on any failure we print an honest error and exit non-0.
|
|
25324
|
+
#
|
|
25325
|
+
# Args: $1 = proof id, $2 = redacted index.html path, $3 = proof.json path.
|
|
25326
|
+
# Returns: 0 on success, non-zero on missing endpoint / transport / non-2xx.
|
|
25327
|
+
_loki_hosted_publish_proof() {
|
|
25328
|
+
local id="$1"
|
|
25329
|
+
local html="$2"
|
|
25330
|
+
local pj="$3"
|
|
25331
|
+
|
|
25332
|
+
# Tier seam (no-op allow for OSS). Hosted publish is opt-in regardless.
|
|
25333
|
+
loki_tier_gate "hosted_publish" || true
|
|
25334
|
+
|
|
25335
|
+
local endpoint="${LOKI_HOSTED_ENDPOINT:-}"
|
|
25336
|
+
if [ -z "$endpoint" ]; then
|
|
25337
|
+
echo -e "${YELLOW}Hosted publishing backend not available.${NC}" >&2
|
|
25338
|
+
echo "There is no official Loki hosted service yet (R9 ships the seam, not a live backend)." >&2
|
|
25339
|
+
echo "To publish to your own hosted endpoint, set LOKI_HOSTED_ENDPOINT to its URL." >&2
|
|
25340
|
+
echo "Or publish to a GitHub Gist instead: loki proof share ${id}" >&2
|
|
25341
|
+
return 1
|
|
25342
|
+
fi
|
|
25343
|
+
|
|
25344
|
+
if ! command -v curl &>/dev/null; then
|
|
25345
|
+
echo -e "${RED}curl not found${NC}" >&2
|
|
25346
|
+
echo "Hosted publishing requires curl. Install curl or use: loki proof share ${id}" >&2
|
|
25347
|
+
return 1
|
|
25348
|
+
fi
|
|
25349
|
+
|
|
25350
|
+
# CREDIBILITY: we upload the file the generator already redacted (the same
|
|
25351
|
+
# bytes 'loki proof share' would put on a gist). We do not build a fresh
|
|
25352
|
+
# body that could bypass redaction. If proof.json reports redaction was not
|
|
25353
|
+
# applied, refuse -- never publish an unredacted artifact.
|
|
25354
|
+
if [ -f "$pj" ]; then
|
|
25355
|
+
local redaction_ok
|
|
25356
|
+
redaction_ok=$(LOKI_PROOF_JSON="$pj" python3 - <<'PYEOF' 2>/dev/null || echo "unknown"
|
|
25357
|
+
import json, os
|
|
25358
|
+
try:
|
|
25359
|
+
d = json.load(open(os.environ["LOKI_PROOF_JSON"]))
|
|
25360
|
+
except Exception:
|
|
25361
|
+
print("unknown")
|
|
25362
|
+
else:
|
|
25363
|
+
print("yes" if (d.get("redaction") or {}).get("applied") else "no")
|
|
25364
|
+
PYEOF
|
|
25365
|
+
)
|
|
25366
|
+
if [ "$redaction_ok" = "no" ]; then
|
|
25367
|
+
echo -e "${RED}Refusing to publish: proof redaction was not applied.${NC}" >&2
|
|
25368
|
+
echo "Regenerate the proof (LOKI_PROOF=1) so the redactor runs, then retry." >&2
|
|
25369
|
+
return 1
|
|
25370
|
+
fi
|
|
25371
|
+
fi
|
|
25372
|
+
|
|
25373
|
+
echo -e "${BOLD}Publishing proof '${id}' to hosted endpoint${NC}"
|
|
25374
|
+
echo " endpoint: ${endpoint}"
|
|
25375
|
+
echo " payload: ${html} (already redacted by the generator)"
|
|
25376
|
+
echo ""
|
|
25377
|
+
|
|
25378
|
+
# POST the redacted HTML. Auth header is sent only if a license key exists;
|
|
25379
|
+
# OSS users with their own endpoint need no key.
|
|
25380
|
+
local tmp_body tmp_code
|
|
25381
|
+
tmp_body=$(mktemp "/tmp/loki-hosted-XXXXXX.out")
|
|
25382
|
+
local -a curl_args=(-sS -o "$tmp_body" -w '%{http_code}' -X POST
|
|
25383
|
+
-H "Content-Type: text/html"
|
|
25384
|
+
-H "X-Loki-Proof-Id: ${id}"
|
|
25385
|
+
--data-binary "@${html}")
|
|
25386
|
+
if [ -n "${LOKI_LICENSE_KEY:-}" ]; then
|
|
25387
|
+
curl_args+=(-H "Authorization: Bearer ${LOKI_LICENSE_KEY}")
|
|
25388
|
+
fi
|
|
25389
|
+
tmp_code=$(curl "${curl_args[@]}" "$endpoint" 2>/dev/null)
|
|
25390
|
+
local curl_exit=$?
|
|
25391
|
+
|
|
25392
|
+
if [ "$curl_exit" -ne 0 ]; then
|
|
25393
|
+
echo -e "${RED}Failed to reach hosted endpoint (curl exit ${curl_exit}).${NC}" >&2
|
|
25394
|
+
echo "Check LOKI_HOSTED_ENDPOINT or publish to a gist: loki proof share ${id}" >&2
|
|
25395
|
+
rm -f "$tmp_body"
|
|
25396
|
+
return 1
|
|
25397
|
+
fi
|
|
25398
|
+
|
|
25399
|
+
# Accept any 2xx. The published URL comes from the endpoint response if it
|
|
25400
|
+
# returns one (we look for a "url" field), else we report the endpoint. We
|
|
25401
|
+
# NEVER print a fabricated URL.
|
|
25402
|
+
case "$tmp_code" in
|
|
25403
|
+
2*)
|
|
25404
|
+
local published_url
|
|
25405
|
+
published_url=$(LOKI_HOSTED_BODY="$tmp_body" LOKI_HOSTED_EP="$endpoint" python3 - <<'PYEOF' 2>/dev/null || true
|
|
25406
|
+
import json, os
|
|
25407
|
+
body_path = os.environ["LOKI_HOSTED_BODY"]
|
|
25408
|
+
try:
|
|
25409
|
+
txt = open(body_path).read().strip()
|
|
25410
|
+
except Exception:
|
|
25411
|
+
txt = ""
|
|
25412
|
+
url = ""
|
|
25413
|
+
try:
|
|
25414
|
+
d = json.loads(txt)
|
|
25415
|
+
if isinstance(d, dict):
|
|
25416
|
+
url = d.get("url") or d.get("public_url") or ""
|
|
25417
|
+
except Exception:
|
|
25418
|
+
url = ""
|
|
25419
|
+
print(url)
|
|
25420
|
+
PYEOF
|
|
25421
|
+
)
|
|
25422
|
+
rm -f "$tmp_body"
|
|
25423
|
+
if [ -n "$published_url" ]; then
|
|
25424
|
+
echo -e "${GREEN}Published: ${published_url}${NC}"
|
|
25425
|
+
else
|
|
25426
|
+
echo -e "${GREEN}Published to ${endpoint} (HTTP ${tmp_code}).${NC}"
|
|
25427
|
+
echo "The endpoint did not return a 'url' field; check your endpoint's response."
|
|
25428
|
+
fi
|
|
25429
|
+
return 0
|
|
25430
|
+
;;
|
|
25431
|
+
*)
|
|
25432
|
+
echo -e "${RED}Hosted endpoint returned HTTP ${tmp_code}.${NC}" >&2
|
|
25433
|
+
if [ -s "$tmp_body" ]; then
|
|
25434
|
+
echo "Response:" >&2
|
|
25435
|
+
head -c 500 "$tmp_body" >&2
|
|
25436
|
+
echo "" >&2
|
|
25437
|
+
fi
|
|
25438
|
+
echo "Nothing was published. Or publish to a gist: loki proof share ${id}" >&2
|
|
25439
|
+
rm -f "$tmp_body"
|
|
25440
|
+
return 1
|
|
25441
|
+
;;
|
|
25442
|
+
esac
|
|
25443
|
+
}
|
|
25444
|
+
|
|
25278
25445
|
# loki bench - head-to-head benchmark harness (R2).
|
|
25279
25446
|
# Subcommands: run <task> | vs <task> | list | verify <result.json>.
|
|
25280
25447
|
# Thin pass-through to benchmarks/bench/run.sh (shared python core runner.py).
|
|
@@ -25342,7 +25509,7 @@ cmd_proof() {
|
|
|
25342
25509
|
echo "Options for 'share':"
|
|
25343
25510
|
echo " --yes Skip the redaction-preview confirmation prompt"
|
|
25344
25511
|
echo " --private Create a secret gist (default: public)"
|
|
25345
|
-
echo " --hosted
|
|
25512
|
+
echo " --hosted Publish to LOKI_HOSTED_ENDPOINT (open-core seam; no official backend yet)"
|
|
25346
25513
|
echo ""
|
|
25347
25514
|
echo "Proofs are generated automatically at run completion (LOKI_PROOF=0 to opt out)."
|
|
25348
25515
|
[ "$sub" = "" ] && exit 1
|
|
@@ -25441,15 +25608,13 @@ PYEOF
|
|
|
25441
25608
|
local id=""
|
|
25442
25609
|
local skip_confirm=0
|
|
25443
25610
|
local visibility="--public"
|
|
25611
|
+
local hosted=0
|
|
25444
25612
|
while [[ $# -gt 0 ]]; do
|
|
25445
25613
|
case "$1" in
|
|
25446
25614
|
--yes|-y) skip_confirm=1; shift ;;
|
|
25447
25615
|
--private) visibility=""; shift ;;
|
|
25448
25616
|
--public) visibility="--public"; shift ;;
|
|
25449
|
-
--hosted)
|
|
25450
|
-
echo -e "${RED}Hosted publishing is not available yet (coming in R9).${NC}"
|
|
25451
|
-
exit 1
|
|
25452
|
-
;;
|
|
25617
|
+
--hosted) hosted=1; shift ;;
|
|
25453
25618
|
-*) echo -e "${RED}Unknown option: $1${NC}"; exit 1 ;;
|
|
25454
25619
|
*) id="$1"; shift ;;
|
|
25455
25620
|
esac
|
|
@@ -25464,6 +25629,17 @@ PYEOF
|
|
|
25464
25629
|
echo "Use 'loki proof list' to see available proofs."
|
|
25465
25630
|
exit 1
|
|
25466
25631
|
fi
|
|
25632
|
+
# R9 open-core hosted-publish seam. Only taken when the user
|
|
25633
|
+
# explicitly passes --hosted. The default gist path below stays
|
|
25634
|
+
# byte-for-byte unchanged for OSS users (zero hosted backend
|
|
25635
|
+
# required). We never silent-fall-back to gist here: the user asked
|
|
25636
|
+
# for hosted, so we POST to a configured LOKI_HOSTED_ENDPOINT or
|
|
25637
|
+
# print an honest "no endpoint configured" message and exit non-zero.
|
|
25638
|
+
# We never fabricate a hosted URL.
|
|
25639
|
+
if [ "$hosted" -eq 1 ]; then
|
|
25640
|
+
_loki_hosted_publish_proof "$id" "$html" "${proofs_dir}/${id}/proof.json"
|
|
25641
|
+
exit $?
|
|
25642
|
+
fi
|
|
25467
25643
|
if ! command -v gh &>/dev/null; then
|
|
25468
25644
|
echo -e "${RED}gh CLI not found${NC}"
|
|
25469
25645
|
echo "Install the GitHub CLI to publish a proof:"
|
package/dashboard/__init__.py
CHANGED
package/docs/INSTALLATION.md
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Loki Mode open-core boundary
|
|
2
|
+
|
|
3
|
+
Loki Mode is and stays open source. This document draws the line between what is
|
|
4
|
+
free forever and what hosted/paid/enterprise plans would add on top. R9 ships
|
|
5
|
+
the SEAMS for that line; it does not ship a hosted backend, a license server, or
|
|
6
|
+
any paywall on existing functionality.
|
|
7
|
+
|
|
8
|
+
## Principle
|
|
9
|
+
|
|
10
|
+
OSS is fully functional with zero hosted backend. Every capability Loki has
|
|
11
|
+
today runs locally, free, with no account, no license key, and no network call
|
|
12
|
+
to any Loki service. Hosted/paid features are ADDITIVE convenience and
|
|
13
|
+
team/enterprise layers, never a removal or gating of something that is free
|
|
14
|
+
today.
|
|
15
|
+
|
|
16
|
+
## Free forever (OSS, the default)
|
|
17
|
+
|
|
18
|
+
Everything that exists today, including:
|
|
19
|
+
|
|
20
|
+
- The full RARV-C autonomous loop (`loki start`), all providers
|
|
21
|
+
(Claude/Cline/Codex/Aider), multi-project, dashboard, memory system.
|
|
22
|
+
- 3-reviewer council + RARV-C closure (the trust engine).
|
|
23
|
+
- proof-of-run generation and local inspection: `loki proof list|show|open`.
|
|
24
|
+
- Sharing a proof to a GitHub Gist: `loki proof share <id>` (uses your own `gh`
|
|
25
|
+
auth; no Loki service involved).
|
|
26
|
+
- Benchmark harness (`loki bench`), healing (`loki heal`), all CLI commands.
|
|
27
|
+
- Self-hosting the hosted publish endpoint: `loki proof share --hosted` posts to
|
|
28
|
+
YOUR `LOKI_HOSTED_ENDPOINT`. Running your own endpoint is free.
|
|
29
|
+
- Enterprise auth seams that already exist and are env-gated, not paywalled:
|
|
30
|
+
token auth (`LOKI_ENTERPRISE_AUTH`), OIDC/SSO (`LOKI_OIDC_*`), audit logging.
|
|
31
|
+
|
|
32
|
+
The default tier is `oss` (`LOKI_TIER` unset or `oss`). In OSS tier the
|
|
33
|
+
tier/license gate is a no-op that allows everything.
|
|
34
|
+
|
|
35
|
+
## What hosted / paid / enterprise would add (seams, not yet built)
|
|
36
|
+
|
|
37
|
+
These are the attachment points R9 reserves. None of them are live; none gate
|
|
38
|
+
any free feature.
|
|
39
|
+
|
|
40
|
+
| Capability | Seam (env / hook) | Status |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| Hosted proof publishing to a managed Loki URL (instead of a gist or self-hosted endpoint) | `LOKI_HOSTED_ENDPOINT` + `loki proof share --hosted` | Seam only. No official Loki endpoint exists. Operators can point it at their own. |
|
|
43
|
+
| Tier / license entitlement | `LOKI_TIER` (default `oss`), `LOKI_LICENSE_KEY`, `loki_tier_gate` (bash) / `tierGate` (Bun) | Seam only. No verification backend. OSS = allow-all no-op. |
|
|
44
|
+
| Managed team memory / cross-project sync | `LOKI_MANAGED_MEMORY` (pre-existing) | Pre-existing gated seam. |
|
|
45
|
+
| Enterprise SSO / RBAC / audit retention | `LOKI_ENTERPRISE_AUTH`, `LOKI_OIDC_*` | Pre-existing env seams (free to self-configure). |
|
|
46
|
+
|
|
47
|
+
A future hosted build would replace the honest stubs (no-op allow / "backend not
|
|
48
|
+
available" messages) with real verification and a managed endpoint. Until then,
|
|
49
|
+
the stubs are labeled honestly and never fabricate a hosted service or URL.
|
|
50
|
+
|
|
51
|
+
## Integrity rules (binding for any future hosted work)
|
|
52
|
+
|
|
53
|
+
1. Never gate or remove a feature that is free today.
|
|
54
|
+
2. Never fabricate a hosted URL, a successful license verification, or a hosted
|
|
55
|
+
service that does not exist. Honest "not available yet" messaging only.
|
|
56
|
+
3. OSS path must work with zero hosted env vars set.
|
|
57
|
+
4. Any artifact published via a hosted seam must pass through the same redactor
|
|
58
|
+
the gist path uses (`proof_redact`); never publish an unredacted artifact.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# R9: Hosted/paid open-core hooks - design note
|
|
2
|
+
|
|
3
|
+
Status: SEAMS implemented (this worktree). NOT a live hosted backend.
|
|
4
|
+
|
|
5
|
+
R9 in the competitive-stickiness arc is the open-core monetization layer: keep
|
|
6
|
+
Loki fully open source and free, while adding the SEAMS where hosted, enterprise,
|
|
7
|
+
and paid plans would attach later. R9 ships the seams only. There is no Loki
|
|
8
|
+
hosted service, no license-verification backend, and no paid gate on any
|
|
9
|
+
existing feature. Every honest stub is labeled as such.
|
|
10
|
+
|
|
11
|
+
## What already existed (verified in source, pre-R9)
|
|
12
|
+
|
|
13
|
+
- proof-of-run `public_url` seam: `autonomy/lib/proof-generator.py:392` writes
|
|
14
|
+
`"deployment": {"deployed_url": deployed_url, "public_url": None}`. The
|
|
15
|
+
`public_url` field is reserved and always null today (no hosted publish wrote
|
|
16
|
+
it). R9 does NOT populate it (see "Deliberate gaps").
|
|
17
|
+
- `loki proof share --hosted` stub: BOTH routes errored "Hosted publishing is
|
|
18
|
+
not available yet (coming in R9)" -- bash `autonomy/loki` (share case in
|
|
19
|
+
`cmd_proof`) and Bun `loki-ts/src/commands/proof.ts` (`shareProof`). This was
|
|
20
|
+
the explicit seam to implement.
|
|
21
|
+
- `loki proof share` (gist): default opt-in publish via `gh gist create`
|
|
22
|
+
through `_loki_gist_upload` (bash) / `shareProof` (Bun). Redaction-preview +
|
|
23
|
+
confirm. This is the free path and stays byte-unchanged.
|
|
24
|
+
- `cmd_enterprise` (`autonomy/loki`): already env-driven feature flags
|
|
25
|
+
(`LOKI_ENTERPRISE_AUTH`, `LOKI_OIDC_ISSUER`/`LOKI_OIDC_CLIENT_ID`,
|
|
26
|
+
`LOKI_AUDIT_DISABLED`/`LOKI_ENTERPRISE_AUTH`). Good precedent: enterprise
|
|
27
|
+
features are env-gated seams, not paywalls. R9 follows the same pattern.
|
|
28
|
+
- No `LOKI_TIER`, `LOKI_LICENSE_KEY`, or `LOKI_HOSTED_ENDPOINT` existed anywhere
|
|
29
|
+
before R9. All three are new with this change.
|
|
30
|
+
- Redaction: the generator redacts the proof ONCE before writing index.html and
|
|
31
|
+
records `redaction.applied` in proof.json (`proof-generator.py`, module
|
|
32
|
+
`proof_redact`). The share path publishes the already-redacted artifact; it
|
|
33
|
+
does not run a second redaction pass.
|
|
34
|
+
|
|
35
|
+
## What R9 adds (seams, no backend)
|
|
36
|
+
|
|
37
|
+
1. Hosted proof-publish seam. `loki proof share --hosted <id>`:
|
|
38
|
+
- If `LOKI_HOSTED_ENDPOINT` is set: POST the ALREADY-REDACTED `index.html`
|
|
39
|
+
(the same bytes the gist path would publish) to that endpoint. On 2xx,
|
|
40
|
+
print the URL the endpoint returned (`url` or `public_url` JSON field), or,
|
|
41
|
+
if none, the endpoint itself + HTTP status. NEVER a fabricated URL.
|
|
42
|
+
- If `LOKI_HOSTED_ENDPOINT` is NOT set: print an honest "Hosted publishing
|
|
43
|
+
backend not available" message (there is no official Loki hosted service
|
|
44
|
+
yet), tell the user to set the env var or use the gist path, and exit
|
|
45
|
+
non-zero. We do NOT silent-fall-back to gist when the user explicitly asked
|
|
46
|
+
for `--hosted` (see "Fallback decision").
|
|
47
|
+
- If proof.json reports `redaction.applied == false`: refuse to publish.
|
|
48
|
+
- bash: `_loki_hosted_publish_proof` (curl). Bun:
|
|
49
|
+
`hostedPublishProof` (fetch). Parity-matched messages + exit codes.
|
|
50
|
+
|
|
51
|
+
2. Tier/license hook. `LOKI_TIER` (default `oss`) + optional `LOKI_LICENSE_KEY`:
|
|
52
|
+
- bash `loki_tier_gate <capability>`; Bun `tierGate(capability)` in
|
|
53
|
+
`loki-ts/src/util/tier.ts`.
|
|
54
|
+
- OSS (the default): always ALLOW, zero notes, no network, no license. This
|
|
55
|
+
is a pure no-op for every OSS user.
|
|
56
|
+
- Non-OSS without a license key: NOT allowed (honest -- we cannot verify an
|
|
57
|
+
entitlement; there is no backend). Never a fabricated grant.
|
|
58
|
+
- Non-OSS with a license key: allow, but flag that the verification backend
|
|
59
|
+
does not exist yet. We do NOT pretend the key was verified.
|
|
60
|
+
- WIRING: the gate is called ONLY from the opt-in `--hosted` seam. It is not
|
|
61
|
+
wired into any existing command path, so it cannot gate a free feature.
|
|
62
|
+
|
|
63
|
+
3. Open-core boundary doc: `docs/OPEN-CORE-BOUNDARY.md` -- what is free forever
|
|
64
|
+
vs. what hosted/paid would add.
|
|
65
|
+
|
|
66
|
+
## Fallback decision (reconciled)
|
|
67
|
+
|
|
68
|
+
The task phrased the fallback two ways. We follow the precise deliverable:
|
|
69
|
+
`share --hosted` with no endpoint prints "set LOKI_HOSTED_ENDPOINT or use gist"
|
|
70
|
+
and EXITS non-zero. We do NOT silently publish to gist when the user explicitly
|
|
71
|
+
asked for `--hosted`. Rationale: silent fallback would surprise a user who
|
|
72
|
+
intended a private/hosted destination by publishing to a public gist instead.
|
|
73
|
+
The plain `loki proof share <id>` (no flag) remains the gist path, unchanged.
|
|
74
|
+
|
|
75
|
+
## OSS-unchanged guarantee
|
|
76
|
+
|
|
77
|
+
- The default `loki proof share` (no `--hosted`) gist path is byte-identical:
|
|
78
|
+
`--hosted` is captured as a mode flag during arg-parse and branches only AFTER
|
|
79
|
+
id + html validation; the gist code below it is untouched.
|
|
80
|
+
- `LOKI_TIER` unset vs set produces identical output/exit for existing commands
|
|
81
|
+
(asserted in tests).
|
|
82
|
+
- No existing env var, command, or default changed behavior.
|
|
83
|
+
|
|
84
|
+
## Deliberate gaps (honest, not omissions)
|
|
85
|
+
|
|
86
|
+
- No live Loki hosted backend, no SaaS, no license server. `--hosted` only works
|
|
87
|
+
against an endpoint the operator supplies. This is by design for R9.
|
|
88
|
+
- `public_url` in proof.json is NOT written back after a hosted publish.
|
|
89
|
+
Mutating the frozen R1 proof artifact post-hoc is risk we deliberately skip;
|
|
90
|
+
the published URL is printed to the user instead. A future release can wire
|
|
91
|
+
write-back once the artifact-mutation story is designed.
|
|
92
|
+
- The tier gate does not verify license keys (no backend). It is a seam only.
|
|
93
|
+
- No retries/backoff on the hosted POST (clean client stub, not a transport
|
|
94
|
+
library).
|
|
95
|
+
|
|
96
|
+
## Tests
|
|
97
|
+
|
|
98
|
+
`loki-ts/tests/commands/proof_hosted_r9.test.ts` (mock endpoint via Bun.serve,
|
|
99
|
+
no network): tier gate OSS allow-all + honest non-OSS; hosted POST hits the
|
|
100
|
+
mocked endpoint with the redacted payload (both bash + Bun routes); honest
|
|
101
|
+
no-endpoint message + non-zero exit; non-2xx honest error; unredacted-proof
|
|
102
|
+
refusal; license-key auth header; OSS-not-gated guarantee (identical output with
|
|
103
|
+
LOKI_TIER unset vs enterprise). Existing `proof.test.ts` parity unchanged.
|
|
104
|
+
|
|
105
|
+
## Files changed
|
|
106
|
+
|
|
107
|
+
- `autonomy/loki` (bash): `loki_tier_gate`, `_loki_hosted_publish_proof`,
|
|
108
|
+
`--hosted` branch in `cmd_proof` share, help text.
|
|
109
|
+
- `loki-ts/src/util/tier.ts` (new): `tierGate`, `currentTier`.
|
|
110
|
+
- `loki-ts/src/commands/proof.ts` (Bun): `hostedPublishProof`, `--hosted`
|
|
111
|
+
branch, help text.
|
|
112
|
+
- `docs/OPEN-CORE-BOUNDARY.md` (new).
|
|
113
|
+
- `loki-ts/tests/commands/proof_hosted_r9.test.ts` (new).
|