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.
Files changed (176) hide show
  1. msg/__init__.py +2 -0
  2. msg/admin/__init__.py +0 -0
  3. msg/admin/backup_retirement.py +56 -0
  4. msg/admin/backups.py +341 -0
  5. msg/admin/custodial_check.py +77 -0
  6. msg/admin/diagnostics.py +750 -0
  7. msg/admin/market.py +91 -0
  8. msg/admin/market_check.py +341 -0
  9. msg/admin/money.py +322 -0
  10. msg/admin/preflight.py +142 -0
  11. msg/admin/recovery_replay.py +281 -0
  12. msg/admin/restore_database.py +37 -0
  13. msg/admin/root.py +347 -0
  14. msg/admin/rotation.py +197 -0
  15. msg/admin/token_delivery_check.py +54 -0
  16. msg/admin/upgrade_check.py +58 -0
  17. msg/application.py +163 -0
  18. msg/bootstrap.py +305 -0
  19. msg/cli.py +537 -0
  20. msg/client.py +725 -0
  21. msg/client_certificates.py +98 -0
  22. msg/client_content.py +43 -0
  23. msg/client_custodial.py +206 -0
  24. msg/client_market.py +104 -0
  25. msg/client_recovery.py +186 -0
  26. msg/client_secrets.py +58 -0
  27. msg/client_tokens.py +99 -0
  28. msg/client_upgrade.py +188 -0
  29. msg/config.py +318 -0
  30. msg/constants.py +11 -0
  31. msg/core/__init__.py +0 -0
  32. msg/core/batching.py +23 -0
  33. msg/core/codec.py +253 -0
  34. msg/core/contracts.py +128 -0
  35. msg/core/cursors.py +68 -0
  36. msg/core/email_address.py +33 -0
  37. msg/core/errors.py +22 -0
  38. msg/core/events.py +6 -0
  39. msg/core/execution_ports.py +20 -0
  40. msg/core/executor.py +193 -0
  41. msg/core/models.py +517 -0
  42. msg/core/packet.py +71 -0
  43. msg/core/permissions.py +14 -0
  44. msg/core/query.py +44 -0
  45. msg/core/read_query.py +60 -0
  46. msg/core/registry.py +173 -0
  47. msg/core/requests.py +58 -0
  48. msg/core/schema_policy.py +28 -0
  49. msg/core/schemas.py +30 -0
  50. msg/core/tags.py +21 -0
  51. msg/core/template_dsl.py +94 -0
  52. msg/core/text_patch.py +283 -0
  53. msg/core/tool_execution.py +28 -0
  54. msg/core/transfer.py +183 -0
  55. msg/daemon.py +255 -0
  56. msg/data/__init__.py +0 -0
  57. msg/data/bootstrap.json +72 -0
  58. msg/data/favicon.png +0 -0
  59. msg/data/logo-dark.svg +5 -0
  60. msg/data/logo.svg +5 -0
  61. msg/data/recovery-checkpoint.example.json +1 -0
  62. msg/data/recovery-checkpoint.schema.json +118 -0
  63. msg/data/shortcodes.json +1 -0
  64. msg/data/system/AGENTS.md +6 -0
  65. msg/data/system/rules/_index.md +17 -0
  66. msg/data/system/rules/auth.md +6 -0
  67. msg/data/system/rules/files.md +6 -0
  68. msg/data/system/rules/identity.md +6 -0
  69. msg/data/system/rules/protocol.md +6 -0
  70. msg/data/system/rules/read-write.md +6 -0
  71. msg/data/system/rules/recovery.md +6 -0
  72. msg/data/system/rules/security.md +10 -0
  73. msg/data/system/rules/topics.md +6 -0
  74. msg/extensions/__init__.py +1 -0
  75. msg/extensions/hosting.py +259 -0
  76. msg/extensions/keystore.py +96 -0
  77. msg/extensions/repositories.py +769 -0
  78. msg/extensions/rss.py +67 -0
  79. msg/extensions/ssh.py +264 -0
  80. msg/extensions/ssh_git.py +300 -0
  81. msg/extensions/tools.py +150 -0
  82. msg/hosting_runtime.py +138 -0
  83. msg/market/__init__.py +1 -0
  84. msg/market/arbitration.py +481 -0
  85. msg/market/delivery.py +338 -0
  86. msg/market/delivery_notifications.py +110 -0
  87. msg/market/delivery_targets.py +76 -0
  88. msg/market/email.py +100 -0
  89. msg/market/escrow.py +345 -0
  90. msg/market/orders.py +218 -0
  91. msg/market/policy.py +147 -0
  92. msg/market/rationale.py +91 -0
  93. msg/market/references.py +19 -0
  94. msg/market/targets.py +157 -0
  95. msg/plugins/__init__.py +28 -0
  96. msg/plugins/achievements.py +316 -0
  97. msg/plugins/batch.py +32 -0
  98. msg/plugins/bounty.py +366 -0
  99. msg/plugins/collaboration.py +261 -0
  100. msg/plugins/common.py +217 -0
  101. msg/plugins/communication.py +853 -0
  102. msg/plugins/content.py +855 -0
  103. msg/plugins/custodial_lifecycle.py +224 -0
  104. msg/plugins/delivery.py +230 -0
  105. msg/plugins/discovery.py +1266 -0
  106. msg/plugins/discussion.py +162 -0
  107. msg/plugins/extensions.py +10 -0
  108. msg/plugins/following.py +78 -0
  109. msg/plugins/hosting_capacity.py +52 -0
  110. msg/plugins/identity.py +1654 -0
  111. msg/plugins/money.py +221 -0
  112. msg/plugins/offers.py +183 -0
  113. msg/plugins/orders.py +273 -0
  114. msg/plugins/recovery.py +376 -0
  115. msg/plugins/schemas.py +5 -0
  116. msg/plugins/sharing.py +300 -0
  117. msg/plugins/store.py +249 -0
  118. msg/plugins/system.py +75 -0
  119. msg/plugins/transfer.py +249 -0
  120. msg/py.typed +0 -0
  121. msg/security/__init__.py +0 -0
  122. msg/security/age_keys.py +112 -0
  123. msg/security/authentication.py +141 -0
  124. msg/security/authorization.py +300 -0
  125. msg/security/backup_retirement.py +135 -0
  126. msg/security/capabilities.py +157 -0
  127. msg/security/certificates.py +183 -0
  128. msg/security/crypto.py +102 -0
  129. msg/security/custodial_migration.py +292 -0
  130. msg/security/custody_history.py +146 -0
  131. msg/security/network.py +81 -0
  132. msg/security/policy.py +67 -0
  133. msg/security/quarantine.py +19 -0
  134. msg/security/root_files.py +67 -0
  135. msg/security/rotation_journal.py +60 -0
  136. msg/security/sealed_box.py +70 -0
  137. msg/security/sharing_policy.py +29 -0
  138. msg/security/token_delivery.py +93 -0
  139. msg/security/vault.py +186 -0
  140. msg/storage/__init__.py +0 -0
  141. msg/storage/capacity.py +100 -0
  142. msg/storage/custodial_migration.py +22 -0
  143. msg/storage/git.py +435 -0
  144. msg/storage/ledger_migration.py +307 -0
  145. msg/storage/market_migration.py +49 -0
  146. msg/storage/postgres.py +663 -0
  147. msg/storage/query.py +39 -0
  148. msg/storage/read_only.py +126 -0
  149. msg/storage/session.py +403 -0
  150. msg/storage/sqlite.py +360 -0
  151. msg/storage/topic_event_migration.py +26 -0
  152. msg/storage/valkey_bus.py +45 -0
  153. msg/transports/__init__.py +0 -0
  154. msg/transports/client.py +183 -0
  155. msg/transports/dictionary.py +387 -0
  156. msg/transports/graphql.py +75 -0
  157. msg/transports/http.py +72 -0
  158. msg/transports/http_routes.py +1577 -0
  159. msg/transports/mcp.py +127 -0
  160. msg/transports/packet.py +42 -0
  161. msg/transports/read_tree_path.py +65 -0
  162. msg/transports/stdio.py +36 -0
  163. msg/transports/url_safety.py +123 -0
  164. msg/tui.py +368 -0
  165. msg/workers/__init__.py +1 -0
  166. msg/workers/effects.py +406 -0
  167. msg/workers/leases.py +19 -0
  168. msg/workers/mail.py +63 -0
  169. msg/workers/maintenance.py +310 -0
  170. msg/workers/sandbox.py +74 -0
  171. msg/workers/sandbox_child.py +189 -0
  172. msg/workers/webhook.py +160 -0
  173. msgctl-0.1.0a1.dist-info/METADATA +96 -0
  174. msgctl-0.1.0a1.dist-info/RECORD +176 -0
  175. msgctl-0.1.0a1.dist-info/WHEEL +4 -0
  176. 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
@@ -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
+ }