@le-space/rootfs 0.6.1 → 0.6.2
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/README.md +4 -0
- package/package.json +1 -1
- package/reference/ucan-store/README.md +89 -0
- package/reference/ucan-store/contract.json +46 -0
- package/reference/ucan-store/rootfs/Dockerfile.rootfs +24 -0
- package/reference/ucan-store/rootfs/README.md +84 -0
- package/reference/ucan-store/rootfs/build-rootfs-image.sh +127 -0
- package/reference/ucan-store/rootfs/build-rootfs.sh +242 -0
- package/reference/ucan-store/rootfs/read-rootfs-contract.py +72 -0
- package/reference/ucan-store/rootfs/ucan-store-autotls-refresh.service +12 -0
- package/reference/ucan-store/rootfs/ucan-store-bootstrap-verify.mjs +409 -0
- package/reference/ucan-store/rootfs/ucan-store-bootstrap.service +21 -0
- package/reference/ucan-store/rootfs/ucan-store-bootstrap.sh +155 -0
- package/reference/ucan-store/rootfs/ucan-store-configure.sh +261 -0
- package/reference/ucan-store/rootfs/ucan-store-describe.py +150 -0
- package/reference/ucan-store/rootfs/ucan-store-request-guard.mjs +740 -0
- package/reference/ucan-store/rootfs/ucan-store-service-start.sh +158 -0
- package/reference/ucan-store/rootfs/ucan-store-setup-server.py +229 -0
- package/reference/ucan-store/rootfs/ucan-store-upload-api-context.js +108 -0
- package/reference/ucan-store/rootfs/ucan-store-upload-api-service-identity.js +116 -0
- package/reference/ucan-store/rootfs/ucan-store.service +19 -0
- package/reference/ucan-store/rootfs/ucan_store_bootstrap_validate.py +226 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ENV_FILE="${ENV_FILE:-/etc/default/ucan-store}"
|
|
5
|
+
READY_FILE="${READY_FILE:-/etc/default/ucan-store.ready}"
|
|
6
|
+
BOOTSTRAP_PACKAGE_FILE="${BOOTSTRAP_PACKAGE_FILE:-/etc/ucan-store/bootstrap-package.json}"
|
|
7
|
+
BOOTSTRAP_VALIDATOR="${BOOTSTRAP_VALIDATOR:-/usr/local/sbin/ucan_store_bootstrap_validate.py}"
|
|
8
|
+
BOOTSTRAP_CRYPTO_VERIFIER="${BOOTSTRAP_CRYPTO_VERIFIER:-/usr/local/sbin/ucan-store-bootstrap-verify.mjs}"
|
|
9
|
+
BOOTSTRAP_VERIFICATION_FILE="${BOOTSTRAP_VERIFICATION_FILE:-/etc/ucan-store/bootstrap-verification.json}"
|
|
10
|
+
SERVICE_NAME="${SERVICE_NAME:-ucan-store.service}"
|
|
11
|
+
CADDY_SERVICE="${CADDY_SERVICE:-caddy.service}"
|
|
12
|
+
CADDYFILE="${CADDYFILE:-/etc/caddy/Caddyfile}"
|
|
13
|
+
SERVICE_PORT="${SERVICE_PORT:-8787}"
|
|
14
|
+
PROXY_PORT="${PROXY_PORT:-8788}"
|
|
15
|
+
PUBLIC_IPV4=""
|
|
16
|
+
PUBLIC_IPV6=""
|
|
17
|
+
PROXY_HOSTNAME=""
|
|
18
|
+
WEBAUTHN_ORIGIN=""
|
|
19
|
+
WEBAUTHN_ORIGIN_FALLBACKS=""
|
|
20
|
+
ADMIN_DID=""
|
|
21
|
+
ADMIN_API_TOKEN=""
|
|
22
|
+
BOOTSTRAP_PACKAGE_INPUT_FILE=""
|
|
23
|
+
START_SERVICE=1
|
|
24
|
+
|
|
25
|
+
usage() {
|
|
26
|
+
cat <<'EOF'
|
|
27
|
+
Usage:
|
|
28
|
+
ucan-store-configure.sh \
|
|
29
|
+
--public-ipv4 <ip> \
|
|
30
|
+
[--public-ipv6 <ipv6>] \
|
|
31
|
+
[--proxy-hostname <hostname>] \
|
|
32
|
+
[--webauthn-origin <origin>] \
|
|
33
|
+
[--webauthn-origin-fallbacks <csv>] \
|
|
34
|
+
[--admin-did <did>] \
|
|
35
|
+
[--admin-api-token <token>] \
|
|
36
|
+
[--bootstrap-package-file <path>] \
|
|
37
|
+
[--no-start]
|
|
38
|
+
|
|
39
|
+
Writes the public service wiring for the current ucan-store deployment,
|
|
40
|
+
enables the guest service, and stores the resulting PWA-facing `VITE_*` values.
|
|
41
|
+
EOF
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
write_env_var() {
|
|
45
|
+
local key="$1"
|
|
46
|
+
local value="$2"
|
|
47
|
+
|
|
48
|
+
python3 - "${ENV_FILE}" "${key}" "${value}" <<'PY'
|
|
49
|
+
import re
|
|
50
|
+
import sys
|
|
51
|
+
from pathlib import Path
|
|
52
|
+
|
|
53
|
+
env_file, key, value = sys.argv[1:4]
|
|
54
|
+
target = Path(env_file)
|
|
55
|
+
pattern = re.compile(rf"^[#\s]*{re.escape(key)}=.*$", re.MULTILINE)
|
|
56
|
+
|
|
57
|
+
raw = target.read_text(encoding="utf-8") if target.exists() else ""
|
|
58
|
+
replacement = f"{key}={value}"
|
|
59
|
+
|
|
60
|
+
if pattern.search(raw):
|
|
61
|
+
updated = pattern.sub(replacement, raw, count=1)
|
|
62
|
+
else:
|
|
63
|
+
updated = raw + ("" if raw.endswith("\n") or not raw else "\n") + replacement + "\n"
|
|
64
|
+
|
|
65
|
+
target.write_text(updated, encoding="utf-8")
|
|
66
|
+
PY
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
write_caddyfile() {
|
|
70
|
+
local hostname="$1"
|
|
71
|
+
mkdir -p "$(dirname "${CADDYFILE}")"
|
|
72
|
+
cat > "${CADDYFILE}" <<EOF
|
|
73
|
+
{
|
|
74
|
+
auto_https disable_redirects
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
${hostname} {
|
|
78
|
+
reverse_proxy 127.0.0.1:${PROXY_PORT}
|
|
79
|
+
}
|
|
80
|
+
EOF
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
derive_service_did_from_hostname() {
|
|
84
|
+
python3 - "${1:-}" <<'PY'
|
|
85
|
+
import sys
|
|
86
|
+
from urllib.parse import urlsplit
|
|
87
|
+
|
|
88
|
+
raw = (sys.argv[1] or "").strip()
|
|
89
|
+
if not raw:
|
|
90
|
+
raise SystemExit(0)
|
|
91
|
+
|
|
92
|
+
parsed = urlsplit(raw if "://" in raw else f"https://{raw}")
|
|
93
|
+
host = (parsed.hostname or "").strip().lower()
|
|
94
|
+
if not host:
|
|
95
|
+
raise SystemExit(0)
|
|
96
|
+
|
|
97
|
+
port = f"%3A{parsed.port}" if parsed.port else ""
|
|
98
|
+
print(f"did:web:{host}{port}")
|
|
99
|
+
PY
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
probe_service_did() {
|
|
103
|
+
python3 - "${SERVICE_PORT}" <<'PY'
|
|
104
|
+
import json
|
|
105
|
+
import sys
|
|
106
|
+
import time
|
|
107
|
+
import urllib.error
|
|
108
|
+
import urllib.request
|
|
109
|
+
|
|
110
|
+
port = int(sys.argv[1])
|
|
111
|
+
url = f"http://127.0.0.1:{port}/.well-known/did.json"
|
|
112
|
+
deadline = time.time() + 60
|
|
113
|
+
last_error = None
|
|
114
|
+
|
|
115
|
+
while time.time() < deadline:
|
|
116
|
+
try:
|
|
117
|
+
with urllib.request.urlopen(url, timeout=5) as response:
|
|
118
|
+
payload = json.loads(response.read().decode("utf-8"))
|
|
119
|
+
did = payload.get("id")
|
|
120
|
+
if isinstance(did, str) and did.strip():
|
|
121
|
+
print(did.strip())
|
|
122
|
+
raise SystemExit(0)
|
|
123
|
+
last_error = "did.json missing id"
|
|
124
|
+
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError) as error:
|
|
125
|
+
last_error = str(error)
|
|
126
|
+
time.sleep(2)
|
|
127
|
+
|
|
128
|
+
raise SystemExit(last_error or "service DID probe timed out")
|
|
129
|
+
PY
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
install_bootstrap_package() {
|
|
133
|
+
local source_file="$1"
|
|
134
|
+
mkdir -p "$(dirname "${BOOTSTRAP_PACKAGE_FILE}")"
|
|
135
|
+
python3 "${BOOTSTRAP_VALIDATOR}" --package-file "${source_file}" >/dev/null
|
|
136
|
+
node "${BOOTSTRAP_CRYPTO_VERIFIER}" \
|
|
137
|
+
--package-file "${source_file}" \
|
|
138
|
+
--admin-did "${ADMIN_DID}" \
|
|
139
|
+
--summary-file "${BOOTSTRAP_VERIFICATION_FILE}" >/dev/null
|
|
140
|
+
cp "${source_file}" "${BOOTSTRAP_PACKAGE_FILE}"
|
|
141
|
+
chmod 0640 "${BOOTSTRAP_PACKAGE_FILE}"
|
|
142
|
+
chmod 0644 "${BOOTSTRAP_VERIFICATION_FILE}"
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
while [ "$#" -gt 0 ]; do
|
|
146
|
+
case "$1" in
|
|
147
|
+
--public-ipv4)
|
|
148
|
+
PUBLIC_IPV4="${2:-}"
|
|
149
|
+
shift 2
|
|
150
|
+
;;
|
|
151
|
+
--public-ipv6)
|
|
152
|
+
PUBLIC_IPV6="${2:-}"
|
|
153
|
+
shift 2
|
|
154
|
+
;;
|
|
155
|
+
--proxy-hostname)
|
|
156
|
+
PROXY_HOSTNAME="${2:-}"
|
|
157
|
+
shift 2
|
|
158
|
+
;;
|
|
159
|
+
--webauthn-origin)
|
|
160
|
+
WEBAUTHN_ORIGIN="${2:-}"
|
|
161
|
+
shift 2
|
|
162
|
+
;;
|
|
163
|
+
--webauthn-origin-fallbacks)
|
|
164
|
+
WEBAUTHN_ORIGIN_FALLBACKS="${2:-}"
|
|
165
|
+
shift 2
|
|
166
|
+
;;
|
|
167
|
+
--admin-did)
|
|
168
|
+
ADMIN_DID="${2:-}"
|
|
169
|
+
shift 2
|
|
170
|
+
;;
|
|
171
|
+
--admin-api-token)
|
|
172
|
+
ADMIN_API_TOKEN="${2:-}"
|
|
173
|
+
shift 2
|
|
174
|
+
;;
|
|
175
|
+
--bootstrap-package-file)
|
|
176
|
+
BOOTSTRAP_PACKAGE_INPUT_FILE="${2:-}"
|
|
177
|
+
shift 2
|
|
178
|
+
;;
|
|
179
|
+
--no-start)
|
|
180
|
+
START_SERVICE=0
|
|
181
|
+
shift
|
|
182
|
+
;;
|
|
183
|
+
-h|--help)
|
|
184
|
+
usage
|
|
185
|
+
exit 0
|
|
186
|
+
;;
|
|
187
|
+
*)
|
|
188
|
+
echo "Unknown argument: $1" >&2
|
|
189
|
+
usage >&2
|
|
190
|
+
exit 1
|
|
191
|
+
;;
|
|
192
|
+
esac
|
|
193
|
+
done
|
|
194
|
+
|
|
195
|
+
if [ -z "${PUBLIC_IPV4}" ]; then
|
|
196
|
+
usage >&2
|
|
197
|
+
exit 1
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
touch "${ENV_FILE}"
|
|
201
|
+
|
|
202
|
+
write_env_var "PUBLIC_IPV4" "${PUBLIC_IPV4}"
|
|
203
|
+
write_env_var "PUBLIC_IPV6" "${PUBLIC_IPV6}"
|
|
204
|
+
write_env_var "PROXY_HOSTNAME" "${PROXY_HOSTNAME}"
|
|
205
|
+
write_env_var "UCAN_STORE_SERVICE_KEY_ALGORITHM" "${UCAN_STORE_SERVICE_KEY_ALGORITHM:-ed25519}"
|
|
206
|
+
write_env_var "UCAN_STORE_ADMIN_DID" "${ADMIN_DID}"
|
|
207
|
+
write_env_var "UCAN_STORE_ADMIN_API_TOKEN" "${ADMIN_API_TOKEN}"
|
|
208
|
+
write_env_var "UCAN_STORE_BOOTSTRAP_PACKAGE_FILE" "${BOOTSTRAP_PACKAGE_FILE}"
|
|
209
|
+
write_env_var "UCAN_STORE_BOOTSTRAP_VERIFICATION_FILE" "${BOOTSTRAP_VERIFICATION_FILE}"
|
|
210
|
+
|
|
211
|
+
if [ -n "${BOOTSTRAP_PACKAGE_INPUT_FILE}" ]; then
|
|
212
|
+
install_bootstrap_package "${BOOTSTRAP_PACKAGE_INPUT_FILE}"
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
if [ -n "${WEBAUTHN_ORIGIN}" ]; then
|
|
216
|
+
write_env_var "WEBAUTHN_ORIGIN" "${WEBAUTHN_ORIGIN}"
|
|
217
|
+
fi
|
|
218
|
+
write_env_var "WEBAUTHN_ORIGIN_FALLBACKS" "${WEBAUTHN_ORIGIN_FALLBACKS}"
|
|
219
|
+
|
|
220
|
+
if [ -n "${PROXY_HOSTNAME}" ]; then
|
|
221
|
+
write_env_var "UCAN_STORE_SERVICE_DID" "$(derive_service_did_from_hostname "${PROXY_HOSTNAME}")"
|
|
222
|
+
write_caddyfile "${PROXY_HOSTNAME}"
|
|
223
|
+
write_env_var "PUBLIC_UPLOAD_SERVICE_URL" "https://${PROXY_HOSTNAME}"
|
|
224
|
+
write_env_var "PUBLIC_REVOCATION_URL" "https://${PROXY_HOSTNAME}"
|
|
225
|
+
write_env_var "PUBLIC_RECEIPTS_URL" "https://${PROXY_HOSTNAME}/receipt/"
|
|
226
|
+
else
|
|
227
|
+
write_env_var "UCAN_STORE_SERVICE_DID" ""
|
|
228
|
+
fi
|
|
229
|
+
|
|
230
|
+
touch "${READY_FILE}"
|
|
231
|
+
|
|
232
|
+
if [ "${START_SERVICE}" = "1" ]; then
|
|
233
|
+
systemctl daemon-reload
|
|
234
|
+
systemctl restart "${SERVICE_NAME}"
|
|
235
|
+
if [ -n "${PROXY_HOSTNAME}" ]; then
|
|
236
|
+
systemctl restart "${CADDY_SERVICE}"
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
SERVICE_DID="$(probe_service_did)"
|
|
240
|
+
write_env_var "UCAN_STORE_SERVICE_DID" "${SERVICE_DID}"
|
|
241
|
+
write_env_var "PUBLIC_UPLOAD_SERVICE_DID" "${SERVICE_DID}"
|
|
242
|
+
write_env_var "PUBLIC_REVOCATION_DID" "${SERVICE_DID}"
|
|
243
|
+
|
|
244
|
+
if [ -f "${BOOTSTRAP_PACKAGE_FILE}" ]; then
|
|
245
|
+
RUNTIME_SERVICE_ORIGIN=""
|
|
246
|
+
if [ -n "${PROXY_HOSTNAME}" ]; then
|
|
247
|
+
RUNTIME_SERVICE_ORIGIN="https://${PROXY_HOSTNAME}"
|
|
248
|
+
fi
|
|
249
|
+
python3 "${BOOTSTRAP_VALIDATOR}" \
|
|
250
|
+
--package-file "${BOOTSTRAP_PACKAGE_FILE}" \
|
|
251
|
+
--runtime-service-did "${SERVICE_DID}" \
|
|
252
|
+
--runtime-service-origin "${RUNTIME_SERVICE_ORIGIN}" \
|
|
253
|
+
--admin-did "${ADMIN_DID}" >/dev/null
|
|
254
|
+
node "${BOOTSTRAP_CRYPTO_VERIFIER}" \
|
|
255
|
+
--package-file "${BOOTSTRAP_PACKAGE_FILE}" \
|
|
256
|
+
--runtime-service-did "${SERVICE_DID}" \
|
|
257
|
+
--runtime-service-origin "${RUNTIME_SERVICE_ORIGIN}" \
|
|
258
|
+
--admin-did "${ADMIN_DID}" \
|
|
259
|
+
--summary-file "${BOOTSTRAP_VERIFICATION_FILE}" >/dev/null
|
|
260
|
+
fi
|
|
261
|
+
fi
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import time
|
|
7
|
+
import urllib.error
|
|
8
|
+
import urllib.request
|
|
9
|
+
|
|
10
|
+
from ucan_store_bootstrap_validate import summarize_bootstrap_package
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
ENV_FILE = os.environ.get("ENV_FILE", "/etc/default/ucan-store")
|
|
14
|
+
SERVICE_PORT = int(os.environ.get("STORACHA_LOCAL_PORT", "8787"))
|
|
15
|
+
WAIT_TIMEOUT_SECONDS = int(os.environ.get("DESCRIBE_WAIT_TIMEOUT_SECONDS", "120"))
|
|
16
|
+
WAIT_INTERVAL_SECONDS = float(os.environ.get("DESCRIBE_WAIT_INTERVAL_SECONDS", "2"))
|
|
17
|
+
BOOTSTRAP_PACKAGE_FILE = os.environ.get(
|
|
18
|
+
"BOOTSTRAP_PACKAGE_FILE",
|
|
19
|
+
"/etc/ucan-store/bootstrap-package.json",
|
|
20
|
+
)
|
|
21
|
+
BOOTSTRAP_VERIFICATION_FILE = os.environ.get(
|
|
22
|
+
"BOOTSTRAP_VERIFICATION_FILE",
|
|
23
|
+
"/etc/ucan-store/bootstrap-verification.json",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def parse_env_file(path: str) -> dict[str, str]:
|
|
28
|
+
values: dict[str, str] = {}
|
|
29
|
+
if not os.path.exists(path):
|
|
30
|
+
return values
|
|
31
|
+
|
|
32
|
+
with open(path, encoding="utf-8") as handle:
|
|
33
|
+
for line in handle:
|
|
34
|
+
stripped = line.strip()
|
|
35
|
+
if not stripped or stripped.startswith("#") or "=" not in stripped:
|
|
36
|
+
continue
|
|
37
|
+
key, value = stripped.split("=", 1)
|
|
38
|
+
values[key.strip()] = value.strip()
|
|
39
|
+
return values
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def fetch_service_did(port: int) -> str:
|
|
43
|
+
url = f"http://127.0.0.1:{port}/.well-known/did.json"
|
|
44
|
+
deadline = time.monotonic() + WAIT_TIMEOUT_SECONDS
|
|
45
|
+
last_error = None
|
|
46
|
+
|
|
47
|
+
while time.monotonic() < deadline:
|
|
48
|
+
try:
|
|
49
|
+
with urllib.request.urlopen(url, timeout=5) as response:
|
|
50
|
+
payload = json.loads(response.read().decode("utf-8"))
|
|
51
|
+
did = payload.get("id")
|
|
52
|
+
if isinstance(did, str) and did.strip():
|
|
53
|
+
return did.strip()
|
|
54
|
+
last_error = "did.json missing id"
|
|
55
|
+
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError) as error:
|
|
56
|
+
last_error = str(error)
|
|
57
|
+
time.sleep(WAIT_INTERVAL_SECONDS)
|
|
58
|
+
|
|
59
|
+
raise SystemExit(last_error or "unable to discover upload service DID")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def read_json_file(path: str) -> dict[str, object] | None:
|
|
63
|
+
if not path or not os.path.exists(path):
|
|
64
|
+
return None
|
|
65
|
+
with open(path, encoding="utf-8") as handle:
|
|
66
|
+
payload = json.load(handle)
|
|
67
|
+
return payload if isinstance(payload, dict) else None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main() -> None:
|
|
71
|
+
env_values = parse_env_file(ENV_FILE)
|
|
72
|
+
service_did = env_values.get("PUBLIC_UPLOAD_SERVICE_DID", "").strip() or fetch_service_did(SERVICE_PORT)
|
|
73
|
+
upload_url = env_values.get("PUBLIC_UPLOAD_SERVICE_URL", "").strip()
|
|
74
|
+
revocation_url = env_values.get("PUBLIC_REVOCATION_URL", "").strip() or upload_url
|
|
75
|
+
receipts_url = env_values.get("PUBLIC_RECEIPTS_URL", "").strip() or (upload_url.rstrip("/") + "/receipt/" if upload_url else "")
|
|
76
|
+
bootstrap_package_file = (
|
|
77
|
+
env_values.get("UCAN_STORE_BOOTSTRAP_PACKAGE_FILE", "").strip()
|
|
78
|
+
or BOOTSTRAP_PACKAGE_FILE
|
|
79
|
+
)
|
|
80
|
+
bootstrap_verification_file = (
|
|
81
|
+
env_values.get("UCAN_STORE_BOOTSTRAP_VERIFICATION_FILE", "").strip()
|
|
82
|
+
or BOOTSTRAP_VERIFICATION_FILE
|
|
83
|
+
)
|
|
84
|
+
bootstrap_validation = summarize_bootstrap_package(
|
|
85
|
+
bootstrap_package_file,
|
|
86
|
+
runtime_service_did=service_did,
|
|
87
|
+
runtime_service_origin=upload_url or None,
|
|
88
|
+
admin_did=env_values.get("UCAN_STORE_ADMIN_DID", "").strip() or None,
|
|
89
|
+
allow_missing=True,
|
|
90
|
+
)
|
|
91
|
+
bootstrap_proof_validation = read_json_file(bootstrap_verification_file)
|
|
92
|
+
if bootstrap_validation.get("status") == "invalid":
|
|
93
|
+
raise SystemExit(
|
|
94
|
+
"bootstrap package validation failed: "
|
|
95
|
+
+ "; ".join(bootstrap_validation.get("errors", [])),
|
|
96
|
+
)
|
|
97
|
+
if bootstrap_proof_validation and bootstrap_proof_validation.get("status") == "invalid":
|
|
98
|
+
raise SystemExit(
|
|
99
|
+
"bootstrap proof verification failed: "
|
|
100
|
+
+ "; ".join(bootstrap_proof_validation.get("errors", [])),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
payload = {
|
|
104
|
+
"service_did": service_did,
|
|
105
|
+
"service_identity": {
|
|
106
|
+
"did": service_did,
|
|
107
|
+
"configured_did": env_values.get("UCAN_STORE_SERVICE_DID", "").strip() or None,
|
|
108
|
+
"key_algorithm": env_values.get(
|
|
109
|
+
"UCAN_STORE_SERVICE_KEY_ALGORITHM",
|
|
110
|
+
"",
|
|
111
|
+
).strip()
|
|
112
|
+
or None,
|
|
113
|
+
},
|
|
114
|
+
"delegation_issuance": {
|
|
115
|
+
"enabled": bool(env_values.get("UCAN_STORE_ADMIN_API_TOKEN", "").strip()),
|
|
116
|
+
"policy_endpoint": f"{upload_url}/admin/delegations/policy" if upload_url else None,
|
|
117
|
+
"issue_endpoint": f"{upload_url}/admin/delegations" if upload_url else None,
|
|
118
|
+
"proof_format": "ucan-car-multibase-base64",
|
|
119
|
+
},
|
|
120
|
+
"service_manifest": {
|
|
121
|
+
"endpoint": f"{upload_url}/.well-known/ucan-store.json" if upload_url else None,
|
|
122
|
+
"alias": f"{upload_url}/service-manifest.json" if upload_url else None,
|
|
123
|
+
"binding": "domain-first",
|
|
124
|
+
},
|
|
125
|
+
"upload_service_url": upload_url or None,
|
|
126
|
+
"upload_service_did": service_did,
|
|
127
|
+
"revocation_url": revocation_url or None,
|
|
128
|
+
"revocation_did": env_values.get("PUBLIC_REVOCATION_DID", "").strip() or service_did,
|
|
129
|
+
"receipts_url": receipts_url or None,
|
|
130
|
+
"proxy_hostname": env_values.get("PROXY_HOSTNAME", "").strip() or None,
|
|
131
|
+
"public_ipv4": env_values.get("PUBLIC_IPV4", "").strip() or None,
|
|
132
|
+
"public_ipv6": env_values.get("PUBLIC_IPV6", "").strip() or None,
|
|
133
|
+
"admin_did": env_values.get("UCAN_STORE_ADMIN_DID", "").strip() or None,
|
|
134
|
+
"webauthn_origin": env_values.get("WEBAUTHN_ORIGIN", "").strip() or None,
|
|
135
|
+
"webauthn_origin_fallbacks": env_values.get("WEBAUTHN_ORIGIN_FALLBACKS", "").strip() or None,
|
|
136
|
+
"bootstrap_validation": bootstrap_validation,
|
|
137
|
+
"bootstrap_proof_validation": bootstrap_proof_validation,
|
|
138
|
+
"pwa_env": {
|
|
139
|
+
"VITE_UPLOAD_SERVICE_URL": upload_url or None,
|
|
140
|
+
"VITE_UPLOAD_SERVICE_DID": service_did,
|
|
141
|
+
"VITE_REVOCATION_URL": revocation_url or None,
|
|
142
|
+
"VITE_REVOCATION_DID": env_values.get("PUBLIC_REVOCATION_DID", "").strip() or service_did,
|
|
143
|
+
"VITE_RECEIPTS_URL": receipts_url or None,
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
print(json.dumps(payload))
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
main()
|