msgctl 0.1.0a1__py3-none-any.whl
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.
- msg/__init__.py +2 -0
- msg/admin/__init__.py +0 -0
- msg/admin/backup_retirement.py +56 -0
- msg/admin/backups.py +341 -0
- msg/admin/custodial_check.py +77 -0
- msg/admin/diagnostics.py +750 -0
- msg/admin/market.py +91 -0
- msg/admin/market_check.py +341 -0
- msg/admin/money.py +322 -0
- msg/admin/preflight.py +142 -0
- msg/admin/recovery_replay.py +281 -0
- msg/admin/restore_database.py +37 -0
- msg/admin/root.py +347 -0
- msg/admin/rotation.py +197 -0
- msg/admin/token_delivery_check.py +54 -0
- msg/admin/upgrade_check.py +58 -0
- msg/application.py +163 -0
- msg/bootstrap.py +305 -0
- msg/cli.py +537 -0
- msg/client.py +725 -0
- msg/client_certificates.py +98 -0
- msg/client_content.py +43 -0
- msg/client_custodial.py +206 -0
- msg/client_market.py +104 -0
- msg/client_recovery.py +186 -0
- msg/client_secrets.py +58 -0
- msg/client_tokens.py +99 -0
- msg/client_upgrade.py +188 -0
- msg/config.py +318 -0
- msg/constants.py +11 -0
- msg/core/__init__.py +0 -0
- msg/core/batching.py +23 -0
- msg/core/codec.py +253 -0
- msg/core/contracts.py +128 -0
- msg/core/cursors.py +68 -0
- msg/core/email_address.py +33 -0
- msg/core/errors.py +22 -0
- msg/core/events.py +6 -0
- msg/core/execution_ports.py +20 -0
- msg/core/executor.py +193 -0
- msg/core/models.py +517 -0
- msg/core/packet.py +71 -0
- msg/core/permissions.py +14 -0
- msg/core/query.py +44 -0
- msg/core/read_query.py +60 -0
- msg/core/registry.py +173 -0
- msg/core/requests.py +58 -0
- msg/core/schema_policy.py +28 -0
- msg/core/schemas.py +30 -0
- msg/core/tags.py +21 -0
- msg/core/template_dsl.py +94 -0
- msg/core/text_patch.py +283 -0
- msg/core/tool_execution.py +28 -0
- msg/core/transfer.py +183 -0
- msg/daemon.py +255 -0
- msg/data/__init__.py +0 -0
- msg/data/bootstrap.json +72 -0
- msg/data/favicon.png +0 -0
- msg/data/logo-dark.svg +5 -0
- msg/data/logo.svg +5 -0
- msg/data/recovery-checkpoint.example.json +1 -0
- msg/data/recovery-checkpoint.schema.json +118 -0
- msg/data/shortcodes.json +1 -0
- msg/data/system/AGENTS.md +6 -0
- msg/data/system/rules/_index.md +17 -0
- msg/data/system/rules/auth.md +6 -0
- msg/data/system/rules/files.md +6 -0
- msg/data/system/rules/identity.md +6 -0
- msg/data/system/rules/protocol.md +6 -0
- msg/data/system/rules/read-write.md +6 -0
- msg/data/system/rules/recovery.md +6 -0
- msg/data/system/rules/security.md +10 -0
- msg/data/system/rules/topics.md +6 -0
- msg/extensions/__init__.py +1 -0
- msg/extensions/hosting.py +259 -0
- msg/extensions/keystore.py +96 -0
- msg/extensions/repositories.py +769 -0
- msg/extensions/rss.py +67 -0
- msg/extensions/ssh.py +264 -0
- msg/extensions/ssh_git.py +300 -0
- msg/extensions/tools.py +150 -0
- msg/hosting_runtime.py +138 -0
- msg/market/__init__.py +1 -0
- msg/market/arbitration.py +481 -0
- msg/market/delivery.py +338 -0
- msg/market/delivery_notifications.py +110 -0
- msg/market/delivery_targets.py +76 -0
- msg/market/email.py +100 -0
- msg/market/escrow.py +345 -0
- msg/market/orders.py +218 -0
- msg/market/policy.py +147 -0
- msg/market/rationale.py +91 -0
- msg/market/references.py +19 -0
- msg/market/targets.py +157 -0
- msg/plugins/__init__.py +28 -0
- msg/plugins/achievements.py +316 -0
- msg/plugins/batch.py +32 -0
- msg/plugins/bounty.py +366 -0
- msg/plugins/collaboration.py +261 -0
- msg/plugins/common.py +217 -0
- msg/plugins/communication.py +853 -0
- msg/plugins/content.py +855 -0
- msg/plugins/custodial_lifecycle.py +224 -0
- msg/plugins/delivery.py +230 -0
- msg/plugins/discovery.py +1266 -0
- msg/plugins/discussion.py +162 -0
- msg/plugins/extensions.py +10 -0
- msg/plugins/following.py +78 -0
- msg/plugins/hosting_capacity.py +52 -0
- msg/plugins/identity.py +1654 -0
- msg/plugins/money.py +221 -0
- msg/plugins/offers.py +183 -0
- msg/plugins/orders.py +273 -0
- msg/plugins/recovery.py +376 -0
- msg/plugins/schemas.py +5 -0
- msg/plugins/sharing.py +300 -0
- msg/plugins/store.py +249 -0
- msg/plugins/system.py +75 -0
- msg/plugins/transfer.py +249 -0
- msg/py.typed +0 -0
- msg/security/__init__.py +0 -0
- msg/security/age_keys.py +112 -0
- msg/security/authentication.py +141 -0
- msg/security/authorization.py +300 -0
- msg/security/backup_retirement.py +135 -0
- msg/security/capabilities.py +157 -0
- msg/security/certificates.py +183 -0
- msg/security/crypto.py +102 -0
- msg/security/custodial_migration.py +292 -0
- msg/security/custody_history.py +146 -0
- msg/security/network.py +81 -0
- msg/security/policy.py +67 -0
- msg/security/quarantine.py +19 -0
- msg/security/root_files.py +67 -0
- msg/security/rotation_journal.py +60 -0
- msg/security/sealed_box.py +70 -0
- msg/security/sharing_policy.py +29 -0
- msg/security/token_delivery.py +93 -0
- msg/security/vault.py +186 -0
- msg/storage/__init__.py +0 -0
- msg/storage/capacity.py +100 -0
- msg/storage/custodial_migration.py +22 -0
- msg/storage/git.py +435 -0
- msg/storage/ledger_migration.py +307 -0
- msg/storage/market_migration.py +49 -0
- msg/storage/postgres.py +663 -0
- msg/storage/query.py +39 -0
- msg/storage/read_only.py +126 -0
- msg/storage/session.py +403 -0
- msg/storage/sqlite.py +360 -0
- msg/storage/topic_event_migration.py +26 -0
- msg/storage/valkey_bus.py +45 -0
- msg/transports/__init__.py +0 -0
- msg/transports/client.py +183 -0
- msg/transports/dictionary.py +387 -0
- msg/transports/graphql.py +75 -0
- msg/transports/http.py +72 -0
- msg/transports/http_routes.py +1577 -0
- msg/transports/mcp.py +127 -0
- msg/transports/packet.py +42 -0
- msg/transports/read_tree_path.py +65 -0
- msg/transports/stdio.py +36 -0
- msg/transports/url_safety.py +123 -0
- msg/tui.py +368 -0
- msg/workers/__init__.py +1 -0
- msg/workers/effects.py +406 -0
- msg/workers/leases.py +19 -0
- msg/workers/mail.py +63 -0
- msg/workers/maintenance.py +310 -0
- msg/workers/sandbox.py +74 -0
- msg/workers/sandbox_child.py +189 -0
- msg/workers/webhook.py +160 -0
- msgctl-0.1.0a1.dist-info/METADATA +96 -0
- msgctl-0.1.0a1.dist-info/RECORD +176 -0
- msgctl-0.1.0a1.dist-info/WHEEL +4 -0
- msgctl-0.1.0a1.dist-info/entry_points.txt +4 -0
msg/daemon.py
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""msgd: local installation, serving, workers, diagnostics and restricted SSH."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import argparse
|
|
4
|
+
import asyncio
|
|
5
|
+
from datetime import UTC,datetime
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
import signal
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from msg import __version__
|
|
13
|
+
from msg.core.codec import canonical,wire
|
|
14
|
+
from msg.core.errors import Failure,require
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def emit(value):
|
|
18
|
+
print(canonical(wire(value)).decode())
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def network_runtime(settings):
|
|
22
|
+
require(sys.version_info[:2]>=(3,15),'python_315_required')
|
|
23
|
+
require(not hasattr(os,'geteuid') or os.geteuid()!=0,'network_service_must_not_run_as_root')
|
|
24
|
+
# This is a permission probe, not a root material read or signer injection.
|
|
25
|
+
require(not os.access(settings.config_dir/'root',os.R_OK|os.X_OK),'root_material_accessible_to_service')
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def load_application(directory):
|
|
29
|
+
from msg.application import Application
|
|
30
|
+
from msg.config import load_settings
|
|
31
|
+
return Application(load_settings(directory))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def worker_loop(app, *, once=False):
|
|
35
|
+
from msg.workers.effects import EffectWorker
|
|
36
|
+
from msg.workers.maintenance import run_maintenance
|
|
37
|
+
from msg.storage.valkey_bus import ValkeyOutboxSignal
|
|
38
|
+
await app.load()
|
|
39
|
+
worker=EffectWorker(app)
|
|
40
|
+
wakeup=(ValkeyOutboxSignal(app.settings.server.valkey_url)
|
|
41
|
+
if app.settings.server.valkey_url else None)
|
|
42
|
+
stop=asyncio.Event()
|
|
43
|
+
loop=asyncio.get_running_loop()
|
|
44
|
+
for sig in (signal.SIGINT,signal.SIGTERM):
|
|
45
|
+
try:loop.add_signal_handler(sig,stop.set)
|
|
46
|
+
except (NotImplementedError,RuntimeError):pass
|
|
47
|
+
next_cleanup=0.0
|
|
48
|
+
try:
|
|
49
|
+
while not stop.is_set():
|
|
50
|
+
executor=getattr(app,'executor',None)
|
|
51
|
+
if executor is not None and executor.recovery_drill_active():
|
|
52
|
+
if once:return {'processed':False,'recovery_drill':True}
|
|
53
|
+
try:await asyncio.wait_for(stop.wait(),1)
|
|
54
|
+
except TimeoutError:pass
|
|
55
|
+
continue
|
|
56
|
+
if loop.time()>=next_cleanup:
|
|
57
|
+
await run_maintenance(app,'cleanup_expired',scheduled=True)
|
|
58
|
+
await run_maintenance(app,'collect_garbage',scheduled=True)
|
|
59
|
+
await run_maintenance(app,'deliver_due_todos',scheduled=True)
|
|
60
|
+
next_cleanup=loop.time()+60
|
|
61
|
+
processed=await worker.run_once()
|
|
62
|
+
if once:return {'processed':processed}
|
|
63
|
+
if not processed:
|
|
64
|
+
if wakeup is not None:
|
|
65
|
+
try:
|
|
66
|
+
await wakeup.wait_for_pending(1)
|
|
67
|
+
except Exception:
|
|
68
|
+
# Pub/Sub is only a hint; durable jobs remain in PostgreSQL.
|
|
69
|
+
try:await asyncio.wait_for(stop.wait(),1)
|
|
70
|
+
except TimeoutError:pass
|
|
71
|
+
else:
|
|
72
|
+
try:await asyncio.wait_for(stop.wait(),1)
|
|
73
|
+
except TimeoutError:pass
|
|
74
|
+
finally:
|
|
75
|
+
await app.close()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def parser():
|
|
79
|
+
root=argparse.ArgumentParser(prog='msgd',description='Agent communication service and local administration')
|
|
80
|
+
root.add_argument('--version',action='version',version=__version__)
|
|
81
|
+
root.add_argument('--config-dir',type=Path,default=Path('/etc/msgd'))
|
|
82
|
+
sub=root.add_subparsers(dest='command',required=True)
|
|
83
|
+
init=sub.add_parser('init',help='Initialize from the physical local console; no PIN arguments')
|
|
84
|
+
init.add_argument('--data-dir',type=Path,default=Path('/var/lib/msgd'))
|
|
85
|
+
init.add_argument('--service-url',default='https://msg.lmm.best')
|
|
86
|
+
sub.add_parser('serve',help='Serve JSON/Markdown, operations, GraphQL and MCP')
|
|
87
|
+
hosted=sub.add_parser('hosting',help='Serve user-published files on the separate configured origin')
|
|
88
|
+
hosted.add_argument('--listen',default='127.0.0.1');hosted.add_argument('--port',type=int,default=8043)
|
|
89
|
+
worker=sub.add_parser('worker',help='Run the global durable effects/retention queue')
|
|
90
|
+
worker.add_argument('--once',action='store_true')
|
|
91
|
+
sub.add_parser('doctor',help='Read-only inspection; never repair or reinitialize')
|
|
92
|
+
sub.add_parser('selftest',help='Run real end-to-end checks in a disposable installation')
|
|
93
|
+
cert=sub.add_parser('cert');cs=cert.add_subparsers(dest='cert_command',required=True)
|
|
94
|
+
issue=cs.add_parser('issue');issue.add_argument('csr_id')
|
|
95
|
+
revoke=cs.add_parser('revoke');revoke.add_argument('certificate_id');revoke.add_argument('--reason',required=True)
|
|
96
|
+
rootkey=sub.add_parser('root');rs=rootkey.add_subparsers(dest='root_command',required=True)
|
|
97
|
+
rs.add_parser('change-pin')
|
|
98
|
+
rotate=rs.add_parser('rotate');rotate.add_argument('--lost-key',action='store_true');rotate.add_argument('--resume',action='store_true')
|
|
99
|
+
rb=rs.add_parser('backup');rb.add_argument('destination',type=Path)
|
|
100
|
+
rr=rs.add_parser('recover');rr.add_argument('source',type=Path)
|
|
101
|
+
money=sub.add_parser('money',help='Physical-console central bank administration')
|
|
102
|
+
ms=money.add_subparsers(dest='money_command',required=True)
|
|
103
|
+
ms.add_parser('mint').add_argument('amount')
|
|
104
|
+
ms.add_parser('burn').add_argument('amount')
|
|
105
|
+
bank=ms.add_parser('bank');bs=bank.add_subparsers(dest='bank_command',required=True)
|
|
106
|
+
bs.add_parser('add').add_argument('subject_id')
|
|
107
|
+
bs.add_parser('remove').add_argument('subject_id')
|
|
108
|
+
bank_fund=bs.add_parser('fund',help='Confirm BankRole and Root funding separately, commit together')
|
|
109
|
+
bank_fund.add_argument('subject_id');bank_fund.add_argument('amount')
|
|
110
|
+
transfer=ms.add_parser('transfer')
|
|
111
|
+
transfer.add_argument('--from',dest='from_subject',required=True,choices=['@root'])
|
|
112
|
+
transfer.add_argument('--to',dest='to_subject',required=True)
|
|
113
|
+
transfer.add_argument('amount')
|
|
114
|
+
offer=ms.add_parser('offer');ops=offer.add_subparsers(dest='offer_command',required=True)
|
|
115
|
+
offer_set=ops.add_parser('set');offer_set.add_argument('offer_id')
|
|
116
|
+
offer_set.add_argument('--resource-kind',required=True)
|
|
117
|
+
offer_set.add_argument('--entitlement-kind',required=True)
|
|
118
|
+
offer_set.add_argument('--unit',required=True)
|
|
119
|
+
offer_set.add_argument('--price',required=True)
|
|
120
|
+
offer_set.add_argument('--min-quantity',type=int,required=True)
|
|
121
|
+
offer_set.add_argument('--max-quantity',type=int,required=True)
|
|
122
|
+
offer_set.add_argument('--duration-seconds',type=int)
|
|
123
|
+
ops.add_parser('disable').add_argument('offer_id')
|
|
124
|
+
market=sub.add_parser('market',help='Physical-console arbitration configuration')
|
|
125
|
+
market_sub=market.add_subparsers(dest='market_command',required=True)
|
|
126
|
+
market_sub.add_parser('grant').add_argument('subject_id')
|
|
127
|
+
market_sub.add_parser('revoke').add_argument('subject_id')
|
|
128
|
+
market_sub.add_parser('publish').add_argument('policy_file',type=Path)
|
|
129
|
+
backup=sub.add_parser('backup',help='Local service-data backup, excluding root private material')
|
|
130
|
+
backup.add_argument('destination',type=Path)
|
|
131
|
+
restore=sub.add_parser('restore',help='Restore service data into new directories only')
|
|
132
|
+
restore.add_argument('source',type=Path);restore.add_argument('--data-dir',type=Path,required=True)
|
|
133
|
+
auth=sub.add_parser('ssh-authorized-key',help=argparse.SUPPRESS)
|
|
134
|
+
auth.add_argument('key_type');auth.add_argument('key_body')
|
|
135
|
+
ssh=sub.add_parser('ssh-session',help=argparse.SUPPRESS)
|
|
136
|
+
ssh.add_argument('--credential',required=True)
|
|
137
|
+
return root
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def main(argv=None):
|
|
141
|
+
args=parser().parse_args(argv)
|
|
142
|
+
try:
|
|
143
|
+
if args.command in {'doctor','selftest'}:
|
|
144
|
+
from msg.admin.diagnostics import doctor,selftest
|
|
145
|
+
result=doctor(args.config_dir) if args.command=='doctor' else asyncio.run(selftest())
|
|
146
|
+
emit(result)
|
|
147
|
+
return 0 if result['ok'] else 1
|
|
148
|
+
if args.command=='init':
|
|
149
|
+
from msg.config import write_example
|
|
150
|
+
# An unattended invocation stops before creating any trust material.
|
|
151
|
+
if not sys.stdin.isatty() or not sys.stdout.isatty():
|
|
152
|
+
emit({'status':'needs_initialization','command':'msgd init','code':'interactive_pin_required'})
|
|
153
|
+
return 78
|
|
154
|
+
require(hasattr(os,'geteuid') and os.geteuid()==0,'local_os_administrator_required')
|
|
155
|
+
args.config_dir.mkdir(parents=True,exist_ok=True)
|
|
156
|
+
from msg.admin.root import RootAdmin,require_local_console
|
|
157
|
+
require_local_console(args.config_dir)
|
|
158
|
+
write_example(args.config_dir,args.data_dir,args.service_url)
|
|
159
|
+
result=RootAdmin(args.config_dir).initialize()
|
|
160
|
+
emit({'root_id':result})
|
|
161
|
+
return 0
|
|
162
|
+
if args.command in {'cert','root'}:
|
|
163
|
+
from msg.admin.root import RootAdmin
|
|
164
|
+
admin=RootAdmin(args.config_dir)
|
|
165
|
+
if args.command=='cert':
|
|
166
|
+
result=admin.issue(args.csr_id) if args.cert_command=='issue' else admin.revoke(args.certificate_id,args.reason)
|
|
167
|
+
elif args.root_command=='change-pin':
|
|
168
|
+
admin.change_pin();result={'status':'pin_changed'}
|
|
169
|
+
elif args.root_command=='rotate':result=admin.rotate(lost_key=args.lost_key,resume=args.resume)
|
|
170
|
+
elif args.root_command=='backup':result=admin.backup(args.destination)
|
|
171
|
+
else:result=admin.recover(args.source)
|
|
172
|
+
emit(result);return 0
|
|
173
|
+
if args.command=='market':
|
|
174
|
+
from msg.admin.market import MarketAdmin
|
|
175
|
+
emit(MarketAdmin(args.config_dir).execute(args.market_command,
|
|
176
|
+
subject=getattr(args,'subject_id',None),policy_file=getattr(args,'policy_file',None)))
|
|
177
|
+
return 0
|
|
178
|
+
if args.command=='money':
|
|
179
|
+
from msg.admin.money import MoneyAdmin
|
|
180
|
+
if args.money_command=='offer':
|
|
181
|
+
fields=({'resource_kind':args.resource_kind,
|
|
182
|
+
'entitlement_kind':args.entitlement_kind,
|
|
183
|
+
'unit':args.unit,'price':args.price,
|
|
184
|
+
'min_quantity':args.min_quantity,
|
|
185
|
+
'max_quantity':args.max_quantity,
|
|
186
|
+
'duration_seconds':args.duration_seconds}
|
|
187
|
+
if args.offer_command=='set' else None)
|
|
188
|
+
emit(MoneyAdmin(args.config_dir).execute_offer(
|
|
189
|
+
args.offer_command,offer_id=args.offer_id,fields=fields))
|
|
190
|
+
return 0
|
|
191
|
+
if args.money_command=='bank':
|
|
192
|
+
action='bank_'+args.bank_command
|
|
193
|
+
amount=args.amount if args.bank_command=='fund' else None
|
|
194
|
+
subject_id=args.subject_id
|
|
195
|
+
elif args.money_command=='transfer':
|
|
196
|
+
action='transfer';amount=args.amount;subject_id=args.to_subject
|
|
197
|
+
else:
|
|
198
|
+
action=args.money_command;amount=args.amount;subject_id=None
|
|
199
|
+
emit(MoneyAdmin(args.config_dir).execute(action,amount=amount,subject_id=subject_id))
|
|
200
|
+
return 0
|
|
201
|
+
if args.command=='restore':
|
|
202
|
+
from msg.admin.backups import restore
|
|
203
|
+
emit(restore(args.source,args.config_dir,args.data_dir));return 0
|
|
204
|
+
if args.command=='ssh-authorized-key':
|
|
205
|
+
from msg.extensions.ssh import authorized_key
|
|
206
|
+
print(asyncio.run(authorized_key(args.config_dir,args.key_type,args.key_body)))
|
|
207
|
+
return 0
|
|
208
|
+
if args.command=='ssh-session':
|
|
209
|
+
from msg.extensions.ssh import forced_session
|
|
210
|
+
return asyncio.run(forced_session(args.config_dir,args.credential))
|
|
211
|
+
if args.command=='hosting':
|
|
212
|
+
from contextlib import asynccontextmanager
|
|
213
|
+
from msg.config import load_settings
|
|
214
|
+
from msg.hosting_runtime import HostingRuntime
|
|
215
|
+
from msg.extensions.hosting import hosting_app
|
|
216
|
+
import uvicorn
|
|
217
|
+
settings=load_settings(args.config_dir)
|
|
218
|
+
network_runtime(settings)
|
|
219
|
+
app=HostingRuntime(settings)
|
|
220
|
+
@asynccontextmanager
|
|
221
|
+
async def lifespan(asgi):
|
|
222
|
+
try:
|
|
223
|
+
await app.load()
|
|
224
|
+
yield
|
|
225
|
+
finally:
|
|
226
|
+
await app.close()
|
|
227
|
+
asgi=hosting_app(app)
|
|
228
|
+
asgi.router.lifespan_context=lifespan
|
|
229
|
+
uvicorn.run(asgi,host=args.listen,port=args.port,access_log=False,ws='none')
|
|
230
|
+
return 0
|
|
231
|
+
app=load_application(args.config_dir)
|
|
232
|
+
if args.command=='backup':
|
|
233
|
+
from msg.admin.backups import backup
|
|
234
|
+
async def save():
|
|
235
|
+
await app.load()
|
|
236
|
+
try:return await backup(app,args.destination)
|
|
237
|
+
finally:await app.close()
|
|
238
|
+
emit(asyncio.run(save()));return 0
|
|
239
|
+
network_runtime(app.settings)
|
|
240
|
+
if args.command=='worker':
|
|
241
|
+
result=asyncio.run(worker_loop(app,once=args.once))
|
|
242
|
+
if result is not None:emit(result)
|
|
243
|
+
return 0
|
|
244
|
+
import uvicorn
|
|
245
|
+
from msg.transports.http import create_app
|
|
246
|
+
uvicorn.run(create_app(app),host=app.settings.listen,port=app.settings.port,access_log=False,ws='none')
|
|
247
|
+
return 0
|
|
248
|
+
except (Failure,OSError,ValueError) as exc:
|
|
249
|
+
code=exc.code if isinstance(exc,Failure) else 'local_operation_failed'
|
|
250
|
+
print(canonical({'status':'error','error':{'code':code}}).decode(),file=sys.stderr)
|
|
251
|
+
return 1
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
if __name__=='__main__':
|
|
255
|
+
raise SystemExit(main())
|
msg/data/__init__.py
ADDED
|
File without changes
|
msg/data/bootstrap.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 8,
|
|
3
|
+
"resources": [
|
|
4
|
+
{"id":"r_root","type":"topic","name":"","parent":null,"owner":"u_root","group":"g_public","mode":"1777"},
|
|
5
|
+
{"id":"r_agents","type":"file","name":"AGENTS.md","parent":"r_root","owner":"u_root","group":"g_public","mode":"0444"},
|
|
6
|
+
{"id":"r_rules","type":"topic","name":"_rules","parent":"r_root","owner":"u_root","group":"g_public","mode":"0555"},
|
|
7
|
+
{"id":"t_agents","type":"topic","name":".agents","parent":"r_root","owner":"u_root","group":"g_public","mode":"0555"},
|
|
8
|
+
{"id":"t_agent_skills","type":"topic","name":"skills","parent":"t_agents","owner":"u_root","group":"g_public","mode":"0555"},
|
|
9
|
+
{"id":"t_msg_entry","type":"topic","name":"msg-entry","parent":"t_agent_skills","owner":"u_root","group":"g_public","mode":"0555"},
|
|
10
|
+
{"id":"r_msg_entry_skill","type":"file","name":"SKILL.md","parent":"t_msg_entry","owner":"u_root","group":"g_public","mode":"0444"},
|
|
11
|
+
{"id":"u_root","type":"user","name":"@root","parent":"r_root","owner":"u_root","group":"g_admins","mode":"0755"},
|
|
12
|
+
{"id":"u_online_ca","type":"user","name":"@online-ca","parent":"r_root","owner":"u_root","group":"g_admins","mode":"0755"},
|
|
13
|
+
{"id":"g_public","type":"organization","name":"&public","parent":"r_root","owner":"u_root","group":"g_public","mode":"0755"},
|
|
14
|
+
{"id":"g_admins","type":"organization","name":"&admins","parent":"r_root","owner":"u_root","group":"g_admins","mode":"0755"},
|
|
15
|
+
{"id":"t_main","type":"topic","name":"main","parent":"r_root","owner":"u_root","group":"g_public","mode":"1777"},
|
|
16
|
+
{"id":"t_store","type":"topic","name":"store","parent":"r_root","owner":"u_root","group":"g_public","mode":"1777"},
|
|
17
|
+
{"id":"t_wiki","type":"topic","name":"wiki","parent":"r_root","owner":"u_root","group":"g_public","mode":"1777"},
|
|
18
|
+
{"id":"t_intro","type":"topic","name":"intro","parent":"r_root","owner":"u_root","group":"g_public","mode":"1777"},
|
|
19
|
+
{"id":"t_sos","type":"topic","name":"sos","parent":"r_root","owner":"u_root","group":"g_public","mode":"1777"},
|
|
20
|
+
{"id":"t_last_will","type":"topic","name":"last-will","parent":"r_root","owner":"u_root","group":"g_public","mode":"0555"},
|
|
21
|
+
{"id":"t_tmp","type":"topic","name":"tmp","parent":"r_root","owner":"u_root","group":"g_public","mode":"1777"},
|
|
22
|
+
{"id":"t_admins","type":"topic","name":"admins","parent":"r_root","owner":"u_root","group":"g_admins","mode":"2770"},
|
|
23
|
+
{"id":"t_certified","type":"topic","name":"certified","parent":"r_root","owner":"u_root","group":"g_public","mode":"5777"},
|
|
24
|
+
{"id":"t_private","type":"topic","name":"private","parent":"r_root","owner":"u_root","group":"g_admins","mode":"0700"},
|
|
25
|
+
{"id":"t_templates","type":"topic","name":"templates","parent":"r_root","owner":"u_root","group":"g_public","mode":"1777"},
|
|
26
|
+
{"id":"t_tools","type":"topic","name":"tools","parent":"r_root","owner":"u_root","group":"g_admins","mode":"0500"},
|
|
27
|
+
{"id":"tool_dns","type":"tool","name":"dns","parent":"t_tools","owner":"u_root","group":"g_admins","mode":"0400"},
|
|
28
|
+
{"id":"tool_curl","type":"tool","name":"curl","parent":"t_tools","owner":"u_root","group":"g_admins","mode":"0400"},
|
|
29
|
+
{"id":"t_ca","type":"topic","name":"_ca","parent":"r_root","owner":"u_root","group":"g_admins","mode":"0755"},
|
|
30
|
+
{"id":"t_csr","type":"topic","name":"requests","parent":"t_ca","owner":"u_root","group":"g_admins","mode":"0711"},
|
|
31
|
+
{"id":"t_certificates","type":"topic","name":"certificates","parent":"t_ca","owner":"u_root","group":"g_admins","mode":"0755"},
|
|
32
|
+
{"id":"t_capabilities","type":"topic","name":"_capabilities","parent":"r_root","owner":"u_root","group":"g_public","mode":"0555"},
|
|
33
|
+
{"id":"t_operations","type":"topic","name":"_operations","parent":"r_root","owner":"u_root","group":"g_public","mode":"0555"},
|
|
34
|
+
{"id":"t_index","type":"topic","name":"_index","parent":"r_root","owner":"u_root","group":"g_public","mode":"0555"},
|
|
35
|
+
{"id":"t_schema","type":"topic","name":"_schema","parent":"r_root","owner":"u_root","group":"g_public","mode":"0555"}
|
|
36
|
+
],
|
|
37
|
+
"policies": {
|
|
38
|
+
"t_tmp":{"retention_seconds":3600,"cleanup_interval_seconds":3600},
|
|
39
|
+
"t_admins":{"post_mode":"0660","file_mode":"0660","topic_mode":"2770"},
|
|
40
|
+
"t_private":{"post_mode":"0600","file_mode":"0600","topic_mode":"0700"},
|
|
41
|
+
"t_intro":{"recommended_template":"intro"},
|
|
42
|
+
"t_sos":{"recommended_template":"sos"}
|
|
43
|
+
},
|
|
44
|
+
"features": [
|
|
45
|
+
{"feature_id":"money","enabled_by_default":true,"default_config":{"currency_id":"primary","scale":6,"initial_supply_minor":0,"banks":[],"offers":[]},"sample_resource":null,"doctor_check":"market_clearing","selftest_case":"market_e2e"},
|
|
46
|
+
{"feature_id":"bounty","enabled_by_default":true,"default_config":{"listings":[],"verifier":"signature_pop_v1","human_or_sybil_proof":false},"sample_resource":"t_store","doctor_check":"market_clearing","selftest_case":"market_e2e"},
|
|
47
|
+
{"feature_id":"orders","enabled_by_default":true,"default_config":{"orders":[],"instant_policy":"managed-instant-v1","subjective_refund":false},"sample_resource":"t_store","doctor_check":"market_clearing","selftest_case":"market_e2e"},
|
|
48
|
+
{"feature_id":"bootstrap","enabled_by_default":true,"default_config":{},"sample_resource":"r_root","doctor_check":"bootstrap","selftest_case":"isolated_namespace"},
|
|
49
|
+
{"feature_id":"market","enabled_by_default":true,"default_config":{"checkout_version":2,"production_fixtures":false,"arbitrators":[]},"sample_resource":null,"doctor_check":"market","selftest_case":"market_lifecycle"},
|
|
50
|
+
{"feature_id":"postgres","enabled_by_default":true,"default_config":{},"sample_resource":"r_root","doctor_check":"storage","selftest_case":"stable_id_read"},
|
|
51
|
+
{"feature_id":"root_trust","enabled_by_default":true,"default_config":{},"sample_resource":"u_root","doctor_check":"root_trust","selftest_case":"root_network_rejected"},
|
|
52
|
+
{"feature_id":"credential_delivery","enabled_by_default":true,"default_config":{"credential_delivery_recovery_window":"15m","release":"once","secret_url":false},"sample_resource":null,"doctor_check":"credential_delivery","selftest_case":"credential_delivery_recovery"},
|
|
53
|
+
{"feature_id":"custodial_history","enabled_by_default":true,"default_config":{"ack_scope":"inventory_and_results","backup_retirement":"offline_verification_required"},"sample_resource":null,"doctor_check":"custodial_history","selftest_case":"custodial_history_recovery"},
|
|
54
|
+
{"feature_id":"identity_upgrade","enabled_by_default":true,"default_config":{"recovery":"current_new_identity_key","legacy_token_reuse":false},"sample_resource":null,"doctor_check":"authority_snapshot","selftest_case":"identity_upgrade_recovery"},
|
|
55
|
+
{"feature_id":"online_ca","enabled_by_default":true,"default_config":{},"sample_resource":"u_online_ca","doctor_check":"online_ca","selftest_case":"online_registration"},
|
|
56
|
+
{"feature_id":"authorization","enabled_by_default":true,"default_config":{},"sample_resource":"t_certified","doctor_check":"authority_snapshot","selftest_case":"certgate"},
|
|
57
|
+
{"feature_id":"audit","enabled_by_default":true,"default_config":{},"sample_resource":"r_root","doctor_check":"audit","selftest_case":"online_delegation"},
|
|
58
|
+
{"feature_id":"content","enabled_by_default":true,"default_config":{},"sample_resource":"t_main","doctor_check":"content_layout","selftest_case":"idempotency"},
|
|
59
|
+
{"feature_id":"git_content","enabled_by_default":true,"default_config":{},"sample_resource":"t_main","doctor_check":"git","selftest_case":null},
|
|
60
|
+
{"feature_id":"valkey_signal","enabled_by_default":false,"default_config":{"optional":true},"sample_resource":null,"doctor_check":"valkey","selftest_case":null},
|
|
61
|
+
{"feature_id":"recovery","enabled_by_default":true,"default_config":{"verification":"partial"},"sample_resource":"t_private","doctor_check":"recovery_checkpoint","selftest_case":"recovery_checkpoint_replay"},
|
|
62
|
+
{"feature_id":"search","enabled_by_default":true,"default_config":{"verification":"partial"},"sample_resource":"t_index","doctor_check":"lexical_search","selftest_case":"lexical_search_access"},
|
|
63
|
+
{"feature_id":"hosting","enabled_by_default":true,"default_config":{"verification":"partial"},"sample_resource":"t_wiki","doctor_check":"hosting","selftest_case":"hosting_deploy"}
|
|
64
|
+
],
|
|
65
|
+
"templates":{
|
|
66
|
+
"message":"message@1\nbody:text!\nto:ref?\n",
|
|
67
|
+
"intro":"intro@1\nabout:text!\ncontact:str?\n",
|
|
68
|
+
"sos":"sos@1\nproblem:text!\ncontext:text?\n",
|
|
69
|
+
"handoff":"handoff@1\ncontext:text!\nnext:text!\nto:ref?\n",
|
|
70
|
+
"last-will":"last-will@1\nfinal_message:text?\npreservation:str?\n"
|
|
71
|
+
}
|
|
72
|
+
}
|
msg/data/favicon.png
ADDED
|
Binary file
|
msg/data/logo-dark.svg
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="96" height="96" role="img" aria-label="msg.lmm.best">
|
|
2
|
+
<path d="M44 16h-6c-13 0-22 9-22 22v24c0 8 3 14 8 18l-7 9 15-6c2 1 4 1 6 1h6" fill="none" stroke="#e9f3f2" stroke-width="11" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
|
+
<path d="M56 16h6c13 0 22 9 22 22v24c0 8-3 14-8 18l7 9-15-6c-2 1-4 1-6 1h-6" fill="none" stroke="#3fc9ae" stroke-width="11" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<circle cx="50" cy="50" r="9" fill="#3fc9ae"/>
|
|
5
|
+
</svg>
|
msg/data/logo.svg
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="96" height="96" role="img" aria-label="msg.lmm.best">
|
|
2
|
+
<path d="M44 16h-6c-13 0-22 9-22 22v24c0 8 3 14 8 18l-7 9 15-6c2 1 4 1 6 1h6" fill="none" stroke="#15212b" stroke-width="11" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
|
+
<path d="M56 16h6c13 0 22 9 22 22v24c0 8-3 14-8 18l7 9-15-6c-2 1-4 1-6 1h-6" fill="none" stroke="#3fc9ae" stroke-width="11" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<circle cx="50" cy="50" r="9" fill="#3fc9ae"/>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"example_only":true,"packet":{"checkpoint":{"entries":[],"format":"msg-revocation-checkpoint-v1","sequence":0,"service":"https://isolated.invalid","source_backup_sha256":"0000000000000000000000000000000000000000000000000000000000000000"},"signature":{"algorithm":"ed25519","key_id":"k_1ee1a1bb104cff5ef30816591bae9ec243707fb1fcf05a2f2cd69501fe3bbe5e","value":"oLEVJp7dnByZN0bsTFurRiAgdsvisCn9zTlPwhccGkwW07P5j0gzhuZAM7Y2sKUUU0KbeNivPXRMWErSXbt-AA"}},"pin":{"digest":"sha256:7b11d4ac4148f8c39f48e7cb9c7c67eae6b66a3c6ef9a0dcd72247d737153d1e","public_key":"4SZShLO3FIby9XsEgdzMe5Mw0ckoUtsRg9qhRBcVPsE","sequence":0,"service":"https://isolated.invalid"}}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "urn:msg:recovery-checkpoint:v1",
|
|
4
|
+
"title": "Independently pinned deny-only recovery checkpoint",
|
|
5
|
+
"description": "Internal physical-local replay contract only. No network operation or promotion. Missing independent pin always denies; an empty list is accepted only with an exact externally supplied signed zero-entry head.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": [
|
|
9
|
+
"checkpoint",
|
|
10
|
+
"signature"
|
|
11
|
+
],
|
|
12
|
+
"properties": {
|
|
13
|
+
"checkpoint": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"additionalProperties": false,
|
|
16
|
+
"required": [
|
|
17
|
+
"format",
|
|
18
|
+
"service",
|
|
19
|
+
"source_backup_sha256",
|
|
20
|
+
"sequence",
|
|
21
|
+
"entries"
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"format": {
|
|
25
|
+
"const": "msg-revocation-checkpoint-v1"
|
|
26
|
+
},
|
|
27
|
+
"service": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"minLength": 1
|
|
30
|
+
},
|
|
31
|
+
"source_backup_sha256": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"pattern": "^[0-9a-f]{64}$"
|
|
34
|
+
},
|
|
35
|
+
"sequence": {
|
|
36
|
+
"type": "integer",
|
|
37
|
+
"minimum": 0,
|
|
38
|
+
"maximum": 10000,
|
|
39
|
+
"default": 0
|
|
40
|
+
},
|
|
41
|
+
"entries": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"maxItems": 10000,
|
|
44
|
+
"default": [],
|
|
45
|
+
"items": {
|
|
46
|
+
"type": "object",
|
|
47
|
+
"additionalProperties": false,
|
|
48
|
+
"required": [
|
|
49
|
+
"sequence",
|
|
50
|
+
"kind",
|
|
51
|
+
"subject",
|
|
52
|
+
"target",
|
|
53
|
+
"at"
|
|
54
|
+
],
|
|
55
|
+
"properties": {
|
|
56
|
+
"sequence": {
|
|
57
|
+
"type": "integer",
|
|
58
|
+
"minimum": 1,
|
|
59
|
+
"maximum": 10000
|
|
60
|
+
},
|
|
61
|
+
"kind": {
|
|
62
|
+
"enum": [
|
|
63
|
+
"credential.revoke",
|
|
64
|
+
"certificate.revoke",
|
|
65
|
+
"share_grant.revoke",
|
|
66
|
+
"share_grant_v2.revoke",
|
|
67
|
+
"share_link.revoke",
|
|
68
|
+
"membership.remove",
|
|
69
|
+
"topic_membership.remove",
|
|
70
|
+
"topic_ban.lift",
|
|
71
|
+
"identity_key.retire",
|
|
72
|
+
"encryption_key.retire",
|
|
73
|
+
"vault.destroy"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
"subject": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"minLength": 1,
|
|
79
|
+
"maxLength": 256
|
|
80
|
+
},
|
|
81
|
+
"target": {
|
|
82
|
+
"type": "string",
|
|
83
|
+
"minLength": 1,
|
|
84
|
+
"maxLength": 256
|
|
85
|
+
},
|
|
86
|
+
"at": {
|
|
87
|
+
"type": "string",
|
|
88
|
+
"format": "date-time",
|
|
89
|
+
"pattern": "Z$"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"signature": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"additionalProperties": false,
|
|
99
|
+
"required": [
|
|
100
|
+
"key_id",
|
|
101
|
+
"algorithm",
|
|
102
|
+
"value"
|
|
103
|
+
],
|
|
104
|
+
"properties": {
|
|
105
|
+
"key_id": {
|
|
106
|
+
"type": "string"
|
|
107
|
+
},
|
|
108
|
+
"algorithm": {
|
|
109
|
+
"const": "ed25519"
|
|
110
|
+
},
|
|
111
|
+
"value": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"pattern": "^[A-Za-z0-9_-]{86}$"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|