@furongjun1999/dsh-memory 0.4.11 → 0.5.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/README.md +16 -16
- package/codebuddy/CODEBUDDY.md +11 -3
- package/codebuddy/README.md +92 -90
- package/codebuddy/mcp.json +27 -27
- package/docs/GBrain/345/217/257/345/200/237/351/211/264/347/202/271_/347/201/265/346/236/242/350/220/275/347/202/271/344/272/244/346/216/245_20260919.md +169 -169
- package/docs/Pi/345/217/257/345/255/246/344/271/240/344/274/230/347/202/271_/347/201/265/346/236/242/345/244/247/350/204/221/346/224/271/350/277/233/344/272/244/346/216/245_20260915.md +144 -144
- package/docs/README.md +142 -111
- package/docs/discipline/harnesses.yaml +244 -226
- package/docs/discipline/templates/full.md.tmpl +61 -61
- package/docs/discipline/templates/rules.mdc.tmpl +68 -0
- package/docs/discipline/templates/skill.md.tmpl +23 -23
- package/docs/eval/AGI/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v1.0.md +299 -299
- package/docs/eval/AGI/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v2.0.md +239 -239
- package/docs/eval//345/256/236/351/252/214/346/226/271/346/241/210_/345/255/246/344/271/240/351/227/255/347/216/257AB/344/270/216/346/250/252/350/257/204_v1.0.md +174 -174
- package/docs/eval//346/250/252/350/257/204_/345/205/255/345/256/266100/351/242/230/344/270/255/350/213/261/345/217/214/346/237/245_v1.0.md +223 -223
- package/docs/{mdcg → hive}//344/273/244/347/211/214/344/270/216/350/247/222/350/211/262/346/235/203/350/201/214/345/210/206/347/246/273_v0.1.md +165 -160
- package/docs/hive//344/273/244/347/211/214/350/257/255/344/271/211/344/277/256/346/255/243_/344/273/262/350/243/201/344/275/215_v0.1.md +76 -0
- package/docs/{mdcg → hive}//345/255/220/344/273/243/347/220/206/351/205/215/347/275/256/346/240/207/345/207/206_v0.5.md +236 -236
- package/docs/hive//346/243/200/347/264/242/346/224/266/346/225/233/345/256/236/346/265/213/344/270/216S1b/350/256/276/350/256/241_v0.1.md +43 -43
- package/docs/hive//346/243/200/347/264/242/347/256/227/346/263/225/345/217/243/345/276/204/345/257/271/347/205/247_v0.1.md +85 -0
- package/docs/hive//346/243/200/347/264/242/350/267/257/345/276/204/344/270/216/350/256/244/347/237/245/347/273/223/346/236/204/345/245/221/347/272/246_v0.1.md +102 -102
- package/docs/hive//350/234/202/345/267/242M6_ingest/345/256/236/346/226/275/350/256/241/345/210/222_v0.1.md +47 -0
- package/docs/hive//350/234/202/345/267/242/345/217/214/345/256/236/344/276/213/344/272/222/351/252/214_/350/256/276/350/256/241/345/256/232/347/250/277.md +503 -503
- package/docs/hive//350/234/202/345/267/242/345/267/245/344/275/234/350/256/260/345/277/206_/351/241/271/347/233/256/350/256/241/345/210/222.md +85 -85
- package/docs/hive//350/234/202/345/267/242/350/256/276/350/256/241_/347/220/206/350/256/272/345/257/271/351/275/220_v0.1.md +191 -0
- package/docs/hive//350/234/202/345/267/242/350/277/255/344/273/243_/345/256/217/350/247/202/344/270/216/347/276/244/344/275/223/350/260/203/345/272/246_v0.1.md +90 -0
- package/docs/mdcg/D_meta_/345/267/245/347/250/213/345/214/226/346/226/271/346/241/210_v0.2.md +216 -216
- package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +646 -646
- package/docs/mdcg/lingshu_tutorial.html +14449 -14449
- package/docs/mdcg/release_v0.4.11.md +49 -0
- package/docs/mdcg/release_v0.4.5.md +55 -55
- package/docs/mdcg/tool_table_v0.3.0.md +117 -117
- package/docs/mdcg//345/205/250/345/272/223/344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/350/256/241/345/210/222_v0.1.md +600 -600
- package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +40 -40
- package/docs/mdcg//345/215/225/345/205/203/350/207/252/346/210/221/351/224/232/347/202/271_/347/263/273/347/273/237/346/217/220/347/244/272/350/257/215/346/240/207/345/207/206_v0.3.md +275 -275
- package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +54 -0
- package/docs/mdcg//346/272/220/347/240/201/347/272/247/346/236/266/346/236/204/345/256/241/350/256/241_GPT/346/211/271/350/257/204/345/257/271/347/205/247_v1.0.md +130 -130
- package/docs/mdcg//347/201/265/346/236/24282/345/267/245/345/205/267_/345/212/237/350/203/275/346/225/264/347/220/206/344/270/216/350/277/201/347/247/273/346/230/240/345/260/204_v0.1.md +278 -278
- package/docs/mdcg//347/201/265/346/236/242/350/256/260/345/277/206/345/212/250/350/257/215/345/215/217/350/256/256_v1.0-draft.md +172 -172
- package/docs/mdcg//347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +270 -270
- package/docs/mdcg//350/256/244/347/237/245/345/233/276_G4-G8/347/274/272/345/217/243/350/243/201/345/256/232/345/215/225_v0.1.md +491 -491
- package/docs/mdcg//350/256/244/347/237/245/345/233/276_/346/235/241/344/273/266/347/251/272/351/227/264/345/220/210/346/210/220/344/270/216/347/224/237/346/225/210/346/235/241/344/273/266/345/217/243/345/276/204_v0.1.md +340 -340
- package/docs/mdcg//350/256/244/347/237/245/345/233/276_/347/264/242/345/274/225/344/270/216/345/267/245/347/250/213/350/247/204/350/214/203/345/214/226_/350/256/241/345/210/222_v0.1.md +588 -588
- package/docs/plans/GridWorld/346/234/200/345/260/217/351/227/255/347/216/257/350/247/204/346/240/274_v0.1.md +176 -176
- package/docs/plans//345/221/275/345/220/215/346/262/273/347/220/206_/351/241/271/347/233/256/350/256/241/345/210/222.md +81 -81
- package/docs/swarm//350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +704 -704
- package/docs/swarm//350/234/202/347/276/244/345/220/214/351/224/231/346/243/200/346/265/213/345/256/236/351/252/214/345/215/217/350/256/256_v0.1.md +242 -242
- package/docs/theory//345/215/225/347/272/277/347/250/213/344/270/216/346/263/250/346/204/217/345/212/233/351/233/206/344/270/255_/346/227/240/344/272/211/350/256/256/347/220/206/350/256/272/346/226/207/346/241/243_v1.0.md +129 -129
- package/docs/theory//345/271/266/345/217/221/345/277/205/347/204/266/346/200/247/347/220/206/350/256/272_v0.2.md +134 -134
- package/docs/theory//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
- package/docs/theory//346/246/202/345/277/265/345/210/206/345/261/202/345/257/271/351/275/220/350/241/250_v0.1.md +145 -145
- package/docs/theory//347/220/206/350/256/272_/346/234/272/345/210/266_/344/273/243/347/240/201_/345/256/236/351/252/214_/347/274/272/345/217/243/347/237/251/351/230/265_v0.1.md +144 -144
- package/docs/theory//347/220/206/350/256/272/344/273/223/346/213/206/345/210/206/344/270/216/347/231/275/347/256/261/347/237/245/350/257/206/345/272/223/345/206/205/350/277/201_v0.1.md +198 -198
- package/docs/theory//350/256/244/347/237/245/344/273/243/347/220/206/344/270/216/346/224/266/346/225/233/347/273/223/346/236/204_/346/235/241/344/273/266/350/256/272/351/207/215/346/236/204_v0.1.md +221 -221
- package/docs/world_model//344/270/226/347/225/214/346/250/241/345/236/213_/347/245/236/347/273/217/347/275/221/347/273/234/345/272/225/345/261/202/346/236/266/346/236/204_v1.0.md +237 -237
- package/docs//345/217/221/345/270/203/344/273/266/345/233/236/346/272/257/350/257/264/346/230/216_v0.1.md +82 -82
- package/docs//345/267/245/344/275/234/347/272/252/345/276/213_/350/256/244/347/237/245/345/233/276/346/235/241/347/233/256_v1.1.json +28 -2
- package/dsh/README.md +82 -82
- package/dsh/cordis.yml.example +139 -139
- package/dsh/update-lingshu.bat +11 -11
- package/lib/hooks.js +36 -2
- package/lib/lib/roleplay_web.js +427 -427
- package/md_cg/__init__.py +7 -7
- package/md_cg/audit.py +368 -368
- package/md_cg/autonomy.py +287 -287
- package/md_cg/backfill.py +1327 -1327
- package/md_cg/backfill_bigdomain.py +34 -34
- package/md_cg/bench6_arms.py +410 -410
- package/md_cg/bench6_common.py +230 -230
- package/md_cg/bench6_competitors.py +212 -212
- package/md_cg/bench_axis_domain.py +257 -257
- package/md_cg/bench_blind_comp.py +308 -308
- package/md_cg/bench_en_atoms_public.py +230 -230
- package/md_cg/bench_governance.py +348 -348
- package/md_cg/bench_lme_zh.py +410 -410
- package/md_cg/bench_locomo.py +121 -121
- package/md_cg/bench_locomo_zh.py +450 -450
- package/md_cg/bench_locomo_zh_public.py +147 -147
- package/md_cg/bench_longmem.py +112 -112
- package/md_cg/bench_membench.py +632 -632
- package/md_cg/bench_p0.py +149 -149
- package/md_cg/bench_progressive.py +287 -287
- package/md_cg/bench_role_views.py +238 -238
- package/md_cg/bench_task_ab.py +243 -243
- package/md_cg/bench_task_ab_llm.py +408 -408
- package/md_cg/bench_unified_en.py +204 -204
- package/md_cg/bench_zh_mad.py +601 -601
- package/md_cg/blindspot_tickets.py +123 -123
- package/md_cg/branches.py +285 -285
- package/md_cg/build_postings.py +73 -73
- package/md_cg/ccgc.py +1005 -948
- package/md_cg/census.py +132 -132
- package/md_cg/chain.py +300 -300
- package/md_cg/codeindex.py +531 -531
- package/md_cg/coldverify.py +292 -292
- package/md_cg/comment_gate.py +337 -337
- package/md_cg/cond_compose.py +190 -190
- package/md_cg/cond_facts.py +154 -154
- package/md_cg/cond_template.json +106 -106
- package/md_cg/condition_anchor.py +142 -142
- package/md_cg/conformance.py +726 -726
- package/md_cg/consistency.py +717 -717
- package/md_cg/consolidate.py +1536 -1439
- package/md_cg/corpus.py +110 -110
- package/md_cg/crosscheck.py +1097 -1097
- package/md_cg/crypto.py +437 -437
- package/md_cg/d_meta.py +310 -310
- package/md_cg/datapath.py +334 -334
- package/md_cg/docindex.py +473 -473
- package/md_cg/eval_common.py +575 -575
- package/md_cg/evidence.py +580 -580
- package/md_cg/evolution.py +477 -477
- package/md_cg/export.py +220 -220
- package/md_cg/forgetting.py +581 -581
- package/md_cg/fsutil.py +329 -329
- package/md_cg/hotcache.py +238 -214
- package/md_cg/hyperedge.py +251 -251
- package/md_cg/identity.py +390 -390
- package/md_cg/insight.py +500 -500
- package/md_cg/interop.py +199 -0
- package/md_cg/lexicon/build_cedict_en_zh.py +329 -329
- package/md_cg/lexicon/build_standard_en.py +171 -171
- package/md_cg/lexicon/expand_en_zh.py +211 -211
- package/md_cg/lifecycle.py +272 -272
- package/md_cg/linkref.py +280 -280
- package/md_cg/links.py +622 -622
- package/md_cg/mcp_server.py +129 -32
- package/md_cg/md_whitebox.py +345 -345
- package/md_cg/mdcg.py +176 -117
- package/md_cg/mdcos.py +79 -13
- package/md_cg/metacognition.py +591 -591
- package/md_cg/migrate.py +119 -119
- package/md_cg/migrate_aeis.py +221 -221
- package/md_cg/migrate_roleplay.py +293 -293
- package/md_cg/migrate_wisdom_graph.py +360 -360
- package/md_cg/mreview/__init__.py +25 -25
- package/md_cg/mreview/__main__.py +110 -110
- package/md_cg/mreview/bundle.py +178 -178
- package/md_cg/mreview/candidates.py +262 -262
- package/md_cg/mreview/govern.py +693 -693
- package/md_cg/mreview/locate.py +939 -939
- package/md_cg/mreview/pipeline.py +728 -728
- package/md_cg/mreview/rules/duplication.json +21 -21
- package/md_cg/mreview/rules/field_coverage.json +54 -54
- package/md_cg/mreview/rules/source_license.json +21 -21
- package/md_cg/mreview/rules/template_flow.json +21 -21
- package/md_cg/mreview/ruleset.py +252 -252
- package/md_cg/nodefile.py +575 -575
- package/md_cg/pooling.py +484 -472
- package/md_cg/postings.py +298 -298
- package/md_cg/predict.py +1100 -1100
- package/md_cg/progressive.py +123 -123
- package/md_cg/protect.py +272 -272
- package/md_cg/protocol/md_cg_gate.proto +33 -33
- package/md_cg/protocol.py +372 -372
- package/md_cg/provenance.py +582 -582
- package/md_cg/reach.py +453 -453
- package/md_cg/readcache.py +85 -0
- package/md_cg/refindex.py +833 -833
- package/md_cg/refine.py +604 -604
- package/md_cg/roleviews.py +89 -89
- package/md_cg/routing.py +365 -365
- package/md_cg/scrub.py +852 -852
- package/md_cg/security.py +274 -274
- package/md_cg/self_state.py +1029 -1029
- package/md_cg/selfreport.py +151 -151
- package/md_cg/semantic/__init__.py +10 -10
- package/md_cg/semantic/canonical.py +122 -122
- package/md_cg/semantic/en_normalizer.py +364 -364
- package/md_cg/semantic/en_zh_map.json +28694 -0
- package/md_cg/semantic/export_en_zh_map.py +64 -0
- package/md_cg/semantic/unify.py +45 -0
- package/md_cg/semantic/zh_en_atoms.py +139 -139
- package/md_cg/signer.py +562 -562
- package/md_cg/sources.py +815 -582
- package/md_cg/statushdr.py +179 -179
- package/md_cg/stg.py +48 -37
- package/md_cg/subgraph.py +729 -729
- package/md_cg/sustain.py +1138 -1138
- package/md_cg/tasks.py +470 -470
- package/md_cg/test_action_derive.py +203 -203
- package/md_cg/test_audit_rotate.py +270 -270
- package/md_cg/test_autonomy.py +143 -143
- package/md_cg/test_bench_governance.py +102 -102
- package/md_cg/test_blindspot_tickets.py +166 -166
- package/md_cg/test_branches.py +249 -249
- package/md_cg/test_ccg_perturb.py +184 -184
- package/md_cg/test_ccgc.py +433 -433
- package/md_cg/test_census_prune.py +81 -81
- package/md_cg/test_cond_compose_anchors.py +76 -76
- package/md_cg/test_cond_match.py +165 -165
- package/md_cg/test_condition_anchor.py +81 -81
- package/md_cg/test_d_meta.py +412 -412
- package/md_cg/test_datapath_root.py +199 -199
- package/md_cg/test_en_pipeline.py +166 -166
- package/md_cg/test_gain_gate.py +212 -212
- package/md_cg/test_health_scale.py +173 -173
- package/md_cg/test_hive_ingest.py +285 -0
- package/md_cg/test_hot_cold.py +215 -215
- package/md_cg/test_hyperedge.py +245 -245
- package/md_cg/test_i26_empty_first_write.py +116 -0
- package/md_cg/test_i27_e041_identity.py +128 -0
- package/md_cg/test_i28_hotcache_prodpath.py +122 -0
- package/md_cg/test_identity_attribution.py +147 -147
- package/md_cg/test_index_durability.py +224 -224
- package/md_cg/test_interop.py +93 -0
- package/md_cg/test_lifecycle.py +309 -309
- package/md_cg/test_linkref.py +306 -306
- package/md_cg/test_lock.py +43 -43
- package/md_cg/test_md_access_parity.py +255 -255
- package/md_cg/test_md_writepath.py +345 -345
- package/md_cg/test_mdstore_search_parity.py +160 -0
- package/md_cg/test_mr_m2.py +587 -587
- package/md_cg/test_mr_m3.py +710 -710
- package/md_cg/test_mr_m4.py +485 -485
- package/md_cg/test_p0.py +250 -250
- package/md_cg/test_p1.py +316 -316
- package/md_cg/test_p10_identity.py +173 -173
- package/md_cg/test_p11_consistency.py +233 -233
- package/md_cg/test_p12_metacognition.py +212 -212
- package/md_cg/test_p13_encryption.py +241 -241
- package/md_cg/test_p14_sustain.py +249 -249
- package/md_cg/test_p15_scrub.py +280 -280
- package/md_cg/test_p16_self_state.py +301 -301
- package/md_cg/test_p17_predict.py +354 -354
- package/md_cg/test_p18_whitebox.py +171 -171
- package/md_cg/test_p19_migrate_roleplay.py +149 -149
- package/md_cg/test_p20_evolution.py +315 -315
- package/md_cg/test_p21_tokens.py +293 -270
- package/md_cg/test_p22_theory.py +175 -175
- package/md_cg/test_p23_links.py +311 -311
- package/md_cg/test_p24_evidence.py +227 -227
- package/md_cg/test_p25_weights.py +156 -156
- package/md_cg/test_p26_refindex.py +416 -416
- package/md_cg/test_p27_docindex.py +765 -765
- package/md_cg/test_p28_refcheck.py +305 -305
- package/md_cg/test_p29_session_ingest_export.py +354 -333
- package/md_cg/test_p3.py +11 -2
- package/md_cg/test_p30_maintain.py +330 -330
- package/md_cg/test_p31_insight.py +534 -534
- package/md_cg/test_p32_backfill.py +298 -298
- package/md_cg/test_p33_ccg_wiring.py +293 -293
- package/md_cg/test_p34_crosscheck.py +331 -331
- package/md_cg/test_p35_conditioned_claim.py +252 -252
- package/md_cg/test_p36_kp_align.py +230 -230
- package/md_cg/test_p37_condition_space.py +248 -248
- package/md_cg/test_p38_concurrent_flush.py +102 -0
- package/md_cg/test_p38_contextualize.py +273 -273
- package/md_cg/test_p39_verify_flow.py +113 -0
- package/md_cg/test_p39_vision_evidence.py +369 -369
- package/md_cg/test_p40_refine_worklist.py +241 -241
- package/md_cg/test_p41_evolve_patrol.py +224 -224
- package/md_cg/test_p42_provenance.py +269 -269
- package/md_cg/test_p43_pooling.py +412 -398
- package/md_cg/test_p44_md_whitebox.py +231 -231
- package/md_cg/test_p45_session_identity.py +219 -219
- package/md_cg/test_p46_unit_scope.py +272 -272
- package/md_cg/test_p47_session_view.py +281 -0
- package/md_cg/test_p4_fuzzy.py +223 -223
- package/md_cg/test_p5_semantic.py +226 -226
- package/md_cg/test_p6_consolidate.py +440 -387
- package/md_cg/test_p7_goals_recent.py +202 -202
- package/md_cg/test_p8_subgraph_chain.py +200 -200
- package/md_cg/test_p9_forget_protect.py +231 -231
- package/md_cg/test_predict_beta.py +135 -135
- package/md_cg/test_preflight_failclosed.py +100 -100
- package/md_cg/test_progressive.py +146 -146
- package/md_cg/test_protocol.py +243 -243
- package/md_cg/test_reach.py +378 -378
- package/md_cg/test_reach_keys.py +201 -201
- package/md_cg/test_read_clip.py +141 -141
- package/md_cg/test_readcache_prodpath.py +155 -0
- package/md_cg/test_retr_gates_prodpath.py +140 -0
- package/md_cg/test_retr_s1.py +340 -340
- package/md_cg/test_retr_s1b.py +209 -209
- package/md_cg/test_retr_s3.py +194 -194
- package/md_cg/test_retr_s4.py +163 -163
- package/md_cg/test_retr_s5.py +200 -200
- package/md_cg/test_retr_s6.py +157 -157
- package/md_cg/test_retr_s7.py +384 -384
- package/md_cg/test_retr_s8_time.py +369 -316
- package/md_cg/test_retr_s9_edges.py +286 -286
- package/md_cg/test_retr_s9_entity_ctx.py +175 -175
- package/md_cg/test_review_conformance.py +367 -367
- package/md_cg/test_role_views.py +354 -354
- package/md_cg/test_sem_noise.py +242 -242
- package/md_cg/test_semantic_canonical.py +241 -241
- package/md_cg/test_subproc_encoding.py +192 -192
- package/md_cg/test_sustain_mutual.py +153 -153
- package/md_cg/test_tasks.py +409 -409
- package/md_cg/test_tool_face.py +189 -189
- package/md_cg/test_transfer.py +180 -180
- package/md_cg/test_trust.py +361 -361
- package/md_cg/test_twophase.py +286 -286
- package/md_cg/test_v14_fixes.py +397 -397
- package/md_cg/test_validity_filter.py +280 -280
- package/md_cg/test_verify_answer.py +138 -138
- package/md_cg/test_wisdom_md_store.py +292 -292
- package/md_cg/test_writelimit.py +197 -197
- package/md_cg/test_writepipe.py +214 -214
- package/md_cg/theory.py +273 -273
- package/md_cg/tokens.py +677 -663
- package/md_cg/tool_face.py +260 -260
- package/md_cg/trust.py +986 -950
- package/md_cg/twophase.py +231 -231
- package/md_cg/units.py +667 -667
- package/md_cg/vision_evidence.py +666 -666
- package/md_cg/weights.py +624 -624
- package/md_cg/whitebox.py +527 -527
- package/md_cg/whitebox_kb/__init__.py +37 -37
- package/md_cg/whitebox_kb/aeis_core/__init__.py +42 -42
- package/md_cg/whitebox_kb/aeis_core/semantic.py +280 -280
- package/md_cg/whitebox_kb/aeis_core/textutil.py +13 -13
- package/md_cg/whitebox_kb/engine.py +310 -310
- package/md_cg/whitebox_kb/seed_knowledge//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
- package/md_cg/whitebox_kb/wisdom/browser_units.py +2631 -2631
- package/md_cg/whitebox_kb/wisdom/causal_discover.py +432 -432
- package/md_cg/whitebox_kb/wisdom/chat_engine.py +1506 -1506
- package/md_cg/whitebox_kb/wisdom/code_solidified.json +6195 -6195
- package/md_cg/whitebox_kb/wisdom/compiler_code_units.py +3033 -3033
- package/md_cg/whitebox_kb/wisdom/condition_algebra.py +112 -112
- package/md_cg/whitebox_kb/wisdom/condition_frame.py +315 -315
- package/md_cg/whitebox_kb/wisdom/condition_kb.py +108 -108
- package/md_cg/whitebox_kb/wisdom/conflict_map.json +4445 -4445
- package/md_cg/whitebox_kb/wisdom/core/lexer.py +512 -512
- package/md_cg/whitebox_kb/wisdom/core/name_checker.py +1023 -1023
- package/md_cg/whitebox_kb/wisdom/cspmn.py +258 -258
- package/md_cg/whitebox_kb/wisdom/csre.py +264 -264
- package/md_cg/whitebox_kb/wisdom/danmaku_audit.py +252 -252
- package/md_cg/whitebox_kb/wisdom/distilled_condition_units.json +6417 -6417
- package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902b.json +1950 -1950
- package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902c.json +1296 -1296
- package/md_cg/whitebox_kb/wisdom/docs/whitebox_capability_graph_demo.json +59 -59
- package/md_cg/whitebox_kb/wisdom/graph_db_units.py +3089 -3089
- package/md_cg/whitebox_kb/wisdom/knowledge_points.py +318 -318
- package/md_cg/whitebox_kb/wisdom/md_access.py +470 -470
- package/md_cg/whitebox_kb/wisdom/md_store.py +276 -251
- package/md_cg/whitebox_kb/wisdom/migrate_wisdom.py +476 -476
- package/md_cg/whitebox_kb/wisdom/navigate.py +248 -248
- package/md_cg/whitebox_kb/wisdom/neural_retrieve.py +224 -224
- package/md_cg/whitebox_kb/wisdom/os_units.py +2735 -2735
- package/md_cg/whitebox_kb/wisdom/pattern_separation.py +376 -376
- package/md_cg/whitebox_kb/wisdom/prereq_map.json +364 -364
- package/md_cg/whitebox_kb/wisdom/python_code_units.py +2766 -2766
- package/md_cg/whitebox_kb/wisdom/role_solidified.json +7 -7
- package/md_cg/whitebox_kb/wisdom/route_memory.py +244 -244
- package/md_cg/whitebox_kb/wisdom/scene_reconstruction.py +148 -148
- package/md_cg/whitebox_kb/wisdom/snr_report.json +40 -40
- package/md_cg/whitebox_kb/wisdom/test_code_compose_domains.py +7541 -7541
- package/md_cg/whitebox_kb/wisdom/test_compiler_self_bootstrap.py +354 -354
- package/md_cg/whitebox_kb/wisdom/test_ecosystem_assembly.py +158 -158
- package/md_cg/whitebox_kb/wisdom/test_ecosystem_demos.py +193 -193
- package/md_cg/whitebox_kb/wisdom/test_graph_db.py +292 -292
- package/md_cg/whitebox_kb/wisdom/test_python_self_bootstrap.py +160 -160
- package/md_cg/whitebox_kb/wisdom/trigger_words_index.json +4366 -4366
- package/md_cg/whitebox_kb/wisdom/verifier.py +1297 -1297
- package/md_cg/writelimit.py +356 -356
- package/md_cg/writepipe.py +550 -542
- package/package.json +97 -96
- package/skills/plugin.json +54 -54
- package/skills/skills/designer-perspective/SKILL.md +158 -158
- package/skills/skills/designer-perspective/references/01-observation-position.md +66 -66
- package/skills/skills/designer-perspective/references/02-structure-recognition.md +62 -62
- package/skills/skills/designer-perspective/references/03-direction-judgment.md +55 -55
- package/skills/skills/designer-perspective/references/04-qualification-verdict.md +72 -72
- package/skills/skills/designer-perspective/references/05-condition-attribution.md +74 -74
- package/skills/skills/designer-perspective/scripts/designer.py +545 -545
- package/skills/skills/designer-perspective/tests/cases.jsonl +17 -17
- package/skills/skills/designer-perspective/tests/selftest.py +61 -61
- package/skills/skills/lingshu-browser/SKILL.md +60 -60
- package/skills/skills/lingshu-compiler/SKILL.md +56 -56
- package/skills/skills/lingshu-compiler/units/analyze-type-infer/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/check-name-real/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-assign/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-expr-tree/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-full-pipeline/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-func-def/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-if-then/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-logic-expr/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-recursive/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-scope/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-type-check/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compile-while/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0010c4bf/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0355bffb/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0361708a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-054a0414/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-05a1691a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-05eeed1e/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0622a1f6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-08b54217/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0a62b70c/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0ab24d00/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0e093688/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0e82b966/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0ee9b9b9/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-0f3787e6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-1028685f/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-11897630/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-16661b9b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-1f722303/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-25be1262/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2a76ba07/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2dbea54a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2df52f16/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2ec2c9d2/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-2f8c8f39/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-38378ac7/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-39457d2e/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-39fb5926/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-47f4fbfa/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4a8cd1f1/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4b230b6b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4cbbda95/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-4d5a68ff/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-56dc9bdd/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-57e76ebe/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-61ff016b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-63eae588/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-64c4224b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-66377955/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-674ab4f6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6af76fd6/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6d979db2/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6de326c0/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-6f1c0eea/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-724d6c9b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-7690177f/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-7b229a7d/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-7f471b3a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-815cad08/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-83c61634/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-8c798c81/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-8dd747ac/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-90324d0a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-94b8d72d/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-94f12231/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-95937c16/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-98a5625b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-98b4c42f/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-98e3894a/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-9bdfe4b8/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-9d9b4e83/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-9f7be5ad/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-a6daf076/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-a7995a0c/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-a8399248/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-aabbd099/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-afe169d8/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b0678bda/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b09bd196/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b1396e23/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-b9b31ce0/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-c10264a7/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-cb1e8e4b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-ccafd438/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-cda9c262/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-ce648068/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-cf5776a4/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-d974e5d3/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-e3979fd3/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-eb1cf2b5/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-ecb30d5b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-f8c8b24b/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-f99fedbe/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-fa8ff5f7/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/compiler-fe1b058d/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/lex-chinese-program/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/lex-dao-de-jing/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/lex-nine-chapters/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-arithmetic/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-array-ops/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-closure-call/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-closure-create/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-compare/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-cond-jump/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-cond-space/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-exception/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-func-call/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-loop-run/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-profiling/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-refcount/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-run-loop/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-short-circuit/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-stack-guard/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-stack-ops/SKILL.md +45 -45
- package/skills/skills/lingshu-compiler/units/vm-trust-accum/SKILL.md +45 -45
- package/skills/skills/lingshu-graph/SKILL.md +63 -63
- package/skills/skills/lingshu-net/SKILL.md +48 -48
- package/skills/skills/lingshu-os/SKILL.md +64 -64
- package/skills/skills/lingshu-pylang/SKILL.md +71 -71
- package/src/bridge.ts +401 -401
- package/src/hooks.ts +38 -2
- package/src/lib/datapath.ts +326 -326
- package/src/lib/mdcg_client.ts +413 -413
- package/src/lib/mutual.ts +428 -428
- package/src/lib/prompt_safety.ts +62 -62
- package/src/lib/python_path.ts +71 -71
- package/src/lib/roleplay_web.ts +932 -932
- package/src/lib/token_store.ts +192 -192
- package/src/tools.ts +212 -212
- package/zcode/AGENTS.md +11 -3
- package/zcode/README.md +41 -41
- /package/docs/{mdcg → hive}//344/270/273/344/273/243/347/220/206/345/255/220/344/273/243/347/220/206/350/256/260/345/277/206/346/236/266/346/236/204/350/256/276/350/256/241.md" +0 -0
package/md_cg/security.py
CHANGED
|
@@ -1,275 +1,275 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""md_cg · 进程/权限模型(记忆 OS #2)
|
|
3
|
-
|
|
4
|
-
关键动机:**灵枢是开源仓库,而记忆很大一部分是私有内容**。因此权限模型必须
|
|
5
|
-
支持「公开知识」与「私有记忆」的物理与逻辑隔离:
|
|
6
|
-
|
|
7
|
-
① 物理隔离:租户(tenant)各自一个根目录。public 租户的根可落在开源仓库内,
|
|
8
|
-
private 租户的根必须落在仓库外(如 ~/.mdcg/private/)。
|
|
9
|
-
② 逻辑隔离:每个节点带 sensitivity(public < internal < private < secret);
|
|
10
|
-
每个调用方(Principal)带 clearance,只能读写 ≤ clearance 的节点。
|
|
11
|
-
③ 硬规则:secret 节点对 clearance < secret 的调用方**写入即拒**(对齐 noema
|
|
12
|
-
「secret 候选自动拒绝」);写入高于自身 clearance 的敏感度 → 拒绝。
|
|
13
|
-
|
|
14
|
-
零第三方依赖。
|
|
15
|
-
"""
|
|
16
|
-
from __future__ import annotations
|
|
17
|
-
|
|
18
|
-
import json
|
|
19
|
-
import os
|
|
20
|
-
import time
|
|
21
|
-
import uuid
|
|
22
|
-
|
|
23
|
-
SENSITIVITY_ORDER = ("public", "internal", "private", "secret")
|
|
24
|
-
DEFAULT_SENSITIVITY = "internal"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class AccessDenied(Exception):
|
|
28
|
-
"""权限拒绝(读/写/管理)。"""
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# 生效条件:形参 level 为模块级常量 SENSITIVITY_ORDER 中的元素时返回其下标,否则抛 AccessDenied。
|
|
32
|
-
def _rank(level: str) -> int:
|
|
33
|
-
try:
|
|
34
|
-
return SENSITIVITY_ORDER.index(level)
|
|
35
|
-
except ValueError:
|
|
36
|
-
raise AccessDenied(f"未知敏感度/密级:{level}") from None
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
# 生效条件:全部形参均可省略、clearance 默认取模块常量 DEFAULT_SENSITIVITY,构造时先经 _rank(clearance) 校验,随后 session 为假值(含空串)回落为 sess_+uuid 十二位、role 假值回落 "system"、expires_at 为假值(含 0)置 None、layers_allow/ops_allow 为 None 时保持 None 否则转 tuple、theory_ok 经 bool() 转换。
|
|
40
|
-
class Principal:
|
|
41
|
-
"""调用方身份(一次会话一个)。
|
|
42
|
-
|
|
43
|
-
tenant —— 租户(决定根目录)
|
|
44
|
-
actor —— 调用者标识(写入审计)
|
|
45
|
-
clearance —— 最高可读/可写敏感度
|
|
46
|
-
can_write —— 是否允许写
|
|
47
|
-
can_admin —— 是否允许管理操作(forget/restore/review_decide)
|
|
48
|
-
session —— 会话 id(进程/会话模型:每次连接一个)
|
|
49
|
-
harness —— 承载端标识(dsh/zcode/codebuddy…;仅归因,不参与授权)
|
|
50
|
-
unit —— 单元分工(record/reflect/verify/output/sustain;仅归因)
|
|
51
|
-
注:MCP 请求级参数 `as_unit` 会经 `tokens.narrowed_principal`
|
|
52
|
-
产出一次性 Principal——其 role/layers/ops 取自该单元 spec、unit
|
|
53
|
-
记为执行单元。那是**单次调用的临时身份**,不改变本字段的归因
|
|
54
|
-
定位(见 `mcp_server.call_tool`)。
|
|
55
|
-
|
|
56
|
-
令牌扩展(由 `tokens.verify_token` 填充;直接构造时为 None = 不限制):
|
|
57
|
-
role —— 角色(designer/reflection/verifier/recorder/output/sustain/guest)
|
|
58
|
-
token_id —— 令牌 id(可追溯到签发记录)
|
|
59
|
-
parent —— 派生来源令牌 id(权职分离的委派链)
|
|
60
|
-
expires_at —— 过期时间戳(None = 不过期)
|
|
61
|
-
layers_allow —— 可写层白名单(None = 不限制;"*" = 全部)
|
|
62
|
-
ops_allow —— 可执行 op 白名单(同上)
|
|
63
|
-
auth_mode —— direct(直接构造)/ token / legacy_env / anonymous
|
|
64
|
-
|
|
65
|
-
版本层扩展(蜂群互联层0,由 `theory.check` 填充):
|
|
66
|
-
theory_ok —— 版本声明是否合法;False 时**全部写/管理操作被拒**(只读降级)
|
|
67
|
-
theory_version —— 当前声明的协议版本(审计与 whoami 用)
|
|
68
|
-
"""
|
|
69
|
-
|
|
70
|
-
# 生效条件:clearance 须为模块级常量 SENSITIVITY_ORDER 成员(否则 _rank 抛 AccessDenied),session 为假值(含 None/空串)时生成 sess_ 随机串,expires_at 为假值(含 None/0)时存 None 否则 float(expires_at),layers_allow/ops_allow 为 None 时存 None 否则 tuple 化。
|
|
71
|
-
def __init__(self, tenant: str = "default", actor: str = "system",
|
|
72
|
-
clearance: str = DEFAULT_SENSITIVITY, can_write: bool = True,
|
|
73
|
-
can_admin: bool = False, session: str = None,
|
|
74
|
-
harness: str = None, unit: str = None,
|
|
75
|
-
role: str = None, token_id: str = None, parent: str = None,
|
|
76
|
-
expires_at: float = None, layers_allow=None, ops_allow=None,
|
|
77
|
-
auth_mode: str = "direct", theory_ok: bool = True,
|
|
78
|
-
theory_version: str = None):
|
|
79
|
-
_rank(clearance) # 校验
|
|
80
|
-
self.tenant = tenant
|
|
81
|
-
self.actor = actor
|
|
82
|
-
self.clearance = clearance
|
|
83
|
-
self.can_write = can_write
|
|
84
|
-
self.can_admin = can_admin
|
|
85
|
-
self.session = session or ("sess_" + uuid.uuid4().hex[:12])
|
|
86
|
-
# 归因维度(嵌套身份):只入审计(_audit/_recent),不参与权限判定。
|
|
87
|
-
# 权限域仍由令牌记录决定(tokens.ROLE_SPECS),与 harness/unit 无关。
|
|
88
|
-
# 受控例外:MCP 请求级 `as_unit` 收窄(tokens.narrowed_principal)产出的是
|
|
89
|
-
# 一次性 Principal,其 role/allow 取自单元 spec——**只做减法**(与 owner
|
|
90
|
-
# 求交 + 管理权恒 False),故不构成本字段「参与授权」的先例。
|
|
91
|
-
self.harness = harness
|
|
92
|
-
self.unit = unit
|
|
93
|
-
self.role = (role or "system")
|
|
94
|
-
self.token_id = token_id
|
|
95
|
-
self.parent = parent
|
|
96
|
-
self.expires_at = float(expires_at) if expires_at else None
|
|
97
|
-
self.layers_allow = None if layers_allow is None else tuple(layers_allow)
|
|
98
|
-
self.ops_allow = None if ops_allow is None else tuple(ops_allow)
|
|
99
|
-
self.auth_mode = auth_mode
|
|
100
|
-
self.theory_ok = bool(theory_ok)
|
|
101
|
-
self.theory_version = theory_version
|
|
102
|
-
|
|
103
|
-
# ---------- 基础判定 ----------
|
|
104
|
-
|
|
105
|
-
# 生效条件:形参 sensitivity 与 self.clearance 均可被 _rank 映射到模块级常量 SENSITIVITY_ORDER 中时,返回前者排名是否不高于后者;任一不在其中则 _rank 抛 AccessDenied。
|
|
106
|
-
def allows(self, sensitivity: str) -> bool:
|
|
107
|
-
"""clearance 是否覆盖该敏感度(可读/可写)。"""
|
|
108
|
-
return _rank(sensitivity) <= _rank(self.clearance)
|
|
109
|
-
|
|
110
|
-
# 生效条件:无 required 形参或模块级常量前置,仅当 self.expires_at(来自 __init__ 的 expires_at)不为 None 且 time.time() 大于它时返回 True,否则返回 False。
|
|
111
|
-
def expired(self) -> bool:
|
|
112
|
-
return self.expires_at is not None and time.time() > self.expires_at
|
|
113
|
-
|
|
114
|
-
@staticmethod
|
|
115
|
-
# 生效条件:allow 为 None 时返回 True(未声明=不限制),allow 非 None 时返回 "'*' in allow 或 name in allow" 的布尔结果。
|
|
116
|
-
def _in_scope(allow, name: str) -> bool:
|
|
117
|
-
if allow is None: # 未声明 = 不限制(兼容直接构造)
|
|
118
|
-
return True
|
|
119
|
-
return "*" in allow or name in allow
|
|
120
|
-
|
|
121
|
-
# 生效条件:layer 为假值(None/空串)时以 "knowledge" 参与判定,返回 self._in_scope(self.layers_allow, layer or "knowledge") 的结果。
|
|
122
|
-
def allows_layer(self, layer: str) -> bool:
|
|
123
|
-
return self._in_scope(self.layers_allow, layer or "knowledge")
|
|
124
|
-
|
|
125
|
-
# 生效条件:op 为假值(None/空串)时以 "" 参与,先经 strip().lower() 归一化,返回 self._in_scope(self.ops_allow, (op or "").strip().lower()) 的结果。
|
|
126
|
-
def allows_op(self, op: str) -> bool:
|
|
127
|
-
return self._in_scope(self.ops_allow, (op or "").strip().lower())
|
|
128
|
-
|
|
129
|
-
# ---------- 强制校验(越权即 AccessDenied) ----------
|
|
130
|
-
|
|
131
|
-
# 生效条件:无 required 形参或模块级常量前置,当 self.expired()(来自 __init__ 的 expires_at 与当前时间比较)为 True 时抛 AccessDenied,否则无操作返回 None。
|
|
132
|
-
def _require_live(self):
|
|
133
|
-
if self.expired():
|
|
134
|
-
raise AccessDenied(f"actor={self.actor} 令牌已过期")
|
|
135
|
-
|
|
136
|
-
# 生效条件:先调用 self._require_live()(过期则抛 AccessDenied);再要求 self.allows_op(op) 为 True,否则抛 AccessDenied。
|
|
137
|
-
def require_op(self, op: str):
|
|
138
|
-
self._require_live()
|
|
139
|
-
if not self.allows_op(op):
|
|
140
|
-
raise AccessDenied(
|
|
141
|
-
f"角色 {self.role} 无权执行 op={op}(作用域 "
|
|
142
|
-
f"{list(self.ops_allow) if self.ops_allow is not None else '不限'})")
|
|
143
|
-
|
|
144
|
-
# 生效条件:依次要求 self._require_live() 未抛异常、self.theory_ok 为 True、self.can_write 为 True、self.allows(sensitivity) 为 True;任一不满足则抛 AccessDenied。
|
|
145
|
-
def require_write(self, sensitivity: str):
|
|
146
|
-
self._require_live()
|
|
147
|
-
if not self.theory_ok:
|
|
148
|
-
raise AccessDenied(
|
|
149
|
-
"版本层校验未通过(theory_ok=False):全部写操作被拒,"
|
|
150
|
-
"仅保留 theory 修复入口")
|
|
151
|
-
if not self.can_write:
|
|
152
|
-
raise AccessDenied(f"actor={self.actor} 无写权限")
|
|
153
|
-
if not self.allows(sensitivity):
|
|
154
|
-
raise AccessDenied(
|
|
155
|
-
f"写入敏感度 {sensitivity} 超出 clearance {self.clearance}")
|
|
156
|
-
|
|
157
|
-
# 生效条件:先要求 self.require_write(sensitivity) 未抛异常;随后将形参 layer 为假值(None/空串)时按 "knowledge" 处理,并要求 self.allows_layer(layer) 为 True,否则抛 AccessDenied。
|
|
158
|
-
def require_layer_write(self, layer: str, sensitivity: str):
|
|
159
|
-
"""写层校验:密级 + 层白名单双闸门(核心私有内容不可越权修改)。"""
|
|
160
|
-
self.require_write(sensitivity)
|
|
161
|
-
layer = layer or "knowledge"
|
|
162
|
-
if not self.allows_layer(layer):
|
|
163
|
-
raise AccessDenied(
|
|
164
|
-
f"角色 {self.role} 无权写入 {layer} 层"
|
|
165
|
-
f"(可写层 {list(self.layers_allow) if self.layers_allow is not None else '不限'})")
|
|
166
|
-
|
|
167
|
-
# 生效条件:要求 self._require_live() 未抛异常、self.theory_ok 为 True、self.can_admin 为 True 时通过;否则抛 AccessDenied(消息用形参 op 标记操作)。
|
|
168
|
-
def require_admin(self, op: str):
|
|
169
|
-
self._require_live()
|
|
170
|
-
if not self.theory_ok:
|
|
171
|
-
raise AccessDenied(
|
|
172
|
-
f"版本层校验未通过(theory_ok=False):管理操作 {op} 被拒")
|
|
173
|
-
if not self.can_admin:
|
|
174
|
-
raise AccessDenied(f"actor={self.actor} 无管理权限({op})")
|
|
175
|
-
|
|
176
|
-
# 生效条件:无 required 形参或模块级常量前置,返回包含 self 各属性(tenant/actor/clearance/can_write/can_admin/session/harness/unit/role/token_id/parent/auth_mode/expires_at/theory_ok/theory_version 及 layers_allow/ops_allow)的 dict;其中 layers_allow/ops_allow 为 None 时值为 None,否则 list 化。
|
|
177
|
-
def as_dict(self):
|
|
178
|
-
return {"tenant": self.tenant, "actor": self.actor,
|
|
179
|
-
"clearance": self.clearance, "can_write": self.can_write,
|
|
180
|
-
"can_admin": self.can_admin, "session": self.session,
|
|
181
|
-
"harness": self.harness, "unit": self.unit,
|
|
182
|
-
"role": self.role, "token_id": self.token_id,
|
|
183
|
-
"parent": self.parent, "auth_mode": self.auth_mode,
|
|
184
|
-
"expires_at": self.expires_at,
|
|
185
|
-
"theory_ok": self.theory_ok,
|
|
186
|
-
"theory_version": self.theory_version,
|
|
187
|
-
"layers_allow": (None if self.layers_allow is None
|
|
188
|
-
else list(self.layers_allow)),
|
|
189
|
-
"ops_allow": (None if self.ops_allow is None
|
|
190
|
-
else list(self.ops_allow))}
|
|
191
|
-
|
|
192
|
-
# 生效条件:无前置;仅返回 tenant/actor/role/clearance/write/admin 的短摘要用于日志与排障,不含 token、密钥材料与能力白名单明细;
|
|
193
|
-
def __repr__(self):
|
|
194
|
-
return (f"Principal(tenant={self.tenant!r}, actor={self.actor!r}, "
|
|
195
|
-
f"role={self.role!r}, clearance={self.clearance!r}, "
|
|
196
|
-
f"write={self.can_write}, admin={self.can_admin})")
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
# 生效条件:path 为 None 时落至 os.path.expanduser("~") 下的 .mdcg/_tenants.json,path 非 None(含空串)时按传入值使用,并在构造内以 self._load() 的返回填充 self.data。
|
|
200
|
-
class TenantRegistry:
|
|
201
|
-
"""租户注册表:tenant → {root, clearance_cap, description}。
|
|
202
|
-
|
|
203
|
-
默认位置:<registry_dir>/_tenants.json(默认 ~/.mdcg/)。
|
|
204
|
-
设计意图:私有租户的 root 指向仓库外目录,开源仓库里只放 public 租户的根。
|
|
205
|
-
"""
|
|
206
|
-
|
|
207
|
-
# 生效条件:形参 path 为 None 时取 ~/.mdcg/_tenants.json,否则取 path;self.data 初始化为 _load() 结果(self.path 经 os.path.exists 为真且 JSON 解析为 dict 时取该 dict,否则回落 {"schema":1,"tenants":{}})。
|
|
208
|
-
def __init__(self, path: str = None):
|
|
209
|
-
if path is None:
|
|
210
|
-
path = os.path.join(os.path.expanduser("~"), ".mdcg", "_tenants.json")
|
|
211
|
-
self.path = path
|
|
212
|
-
self.data = self._load()
|
|
213
|
-
|
|
214
|
-
# 生效条件:当 self.path 经 os.path.exists 为真且内容可解析为 dict 时返回该 dict;否则(os.path.exists 为假、非 dict、JSON 解析失败或 OSError)返回 {"schema":1,"tenants":{}}。
|
|
215
|
-
def _load(self):
|
|
216
|
-
if os.path.exists(self.path):
|
|
217
|
-
try:
|
|
218
|
-
with open(self.path, encoding="utf-8") as f:
|
|
219
|
-
d = json.load(f)
|
|
220
|
-
if isinstance(d, dict):
|
|
221
|
-
return d
|
|
222
|
-
except (ValueError, OSError):
|
|
223
|
-
pass
|
|
224
|
-
return {"schema": 1, "tenants": {}}
|
|
225
|
-
|
|
226
|
-
# 生效条件:无 required 形参或模块级常量前置,将 self.data 以 JSON 写入 self.path + ".tmp",随后 os.replace 到 self.path;目录名称为空时用 "." 创建。
|
|
227
|
-
def _save(self):
|
|
228
|
-
os.makedirs(os.path.dirname(self.path) or ".", exist_ok=True)
|
|
229
|
-
tmp = self.path + ".tmp"
|
|
230
|
-
with open(tmp, "w", encoding="utf-8") as f:
|
|
231
|
-
json.dump(self.data, f, ensure_ascii=False, indent=1)
|
|
232
|
-
os.replace(tmp, self.path)
|
|
233
|
-
|
|
234
|
-
# 生效条件:形参 clearance_cap 须为模块级常量 SENSITIVITY_ORDER 成员(否则 _rank 抛 AccessDenied);形参 tenant/root 提供后写入 self.data["tenants"](要求 self.data 含 "tenants" 键,否则 KeyError),_save 成功则返回新登记项。
|
|
235
|
-
def register(self, tenant: str, root: str, clearance_cap: str = DEFAULT_SENSITIVITY,
|
|
236
|
-
description: str = ""):
|
|
237
|
-
_rank(clearance_cap)
|
|
238
|
-
self.data["tenants"][tenant] = {
|
|
239
|
-
"root": os.path.abspath(root),
|
|
240
|
-
"clearance_cap": clearance_cap,
|
|
241
|
-
"description": description,
|
|
242
|
-
"registered_at": time.time(),
|
|
243
|
-
}
|
|
244
|
-
self._save()
|
|
245
|
-
return self.data["tenants"][tenant]
|
|
246
|
-
|
|
247
|
-
# 生效条件:self.data 含 "tenants" 键(否则 KeyError),且该映射中存在形参 tenant 时返回其值,否则返回 None(.get 缺键回落 None,键存在值为 None 也返回 None)。
|
|
248
|
-
def get(self, tenant: str):
|
|
249
|
-
return self.data["tenants"].get(tenant)
|
|
250
|
-
|
|
251
|
-
# 生效条件:self.get(tenant) 返回真值(非 None/空 dict 等)时返回 t["root"](若 t 无 "root" 键则 KeyError);返回假值时返回 None。
|
|
252
|
-
def root_of(self, tenant: str):
|
|
253
|
-
t = self.get(tenant)
|
|
254
|
-
return t["root"] if t else None
|
|
255
|
-
|
|
256
|
-
# 生效条件:self.get(tenant) 返回真值时返回 t["clearance_cap"](缺键则 KeyError);返回假值时返回模块级常量 DEFAULT_SENSITIVITY。
|
|
257
|
-
def cap_of(self, tenant: str):
|
|
258
|
-
t = self.get(tenant)
|
|
259
|
-
return t["clearance_cap"] if t else DEFAULT_SENSITIVITY
|
|
260
|
-
|
|
261
|
-
# 生效条件:self.data 含 "tenants" 键时返回其浅拷贝 dict(self.data["tenants"]);该键缺失时按 self.data["tenants"] 取值会 KeyError,无默认回落。
|
|
262
|
-
def all(self):
|
|
263
|
-
return dict(self.data["tenants"])
|
|
264
|
-
|
|
265
|
-
# 生效条件:cap 由 cap_of(tenant) 决定(形参 tenant 未注册时取模块级常量 DEFAULT_SENSITIVITY);clearance 为假值(含 None/空串)时 want 取 cap,否则先取 clearance,再在 _rank(want) > _rank(cap) 时夹紧为 cap;actor 为假值时取 tenant;返回 Principal(...)。
|
|
266
|
-
def principal_for(self, tenant: str, actor: str = None, clearance: str = None,
|
|
267
|
-
can_write: bool = True, can_admin: bool = False,
|
|
268
|
-
session: str = None) -> Principal:
|
|
269
|
-
"""按租户上限夹紧 clearance(调用方不能超过租户上限)。"""
|
|
270
|
-
cap = self.cap_of(tenant)
|
|
271
|
-
want = clearance or cap
|
|
272
|
-
if _rank(want) > _rank(cap):
|
|
273
|
-
want = cap
|
|
274
|
-
return Principal(tenant=tenant, actor=actor or tenant, clearance=want,
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""md_cg · 进程/权限模型(记忆 OS #2)
|
|
3
|
+
|
|
4
|
+
关键动机:**灵枢是开源仓库,而记忆很大一部分是私有内容**。因此权限模型必须
|
|
5
|
+
支持「公开知识」与「私有记忆」的物理与逻辑隔离:
|
|
6
|
+
|
|
7
|
+
① 物理隔离:租户(tenant)各自一个根目录。public 租户的根可落在开源仓库内,
|
|
8
|
+
private 租户的根必须落在仓库外(如 ~/.mdcg/private/)。
|
|
9
|
+
② 逻辑隔离:每个节点带 sensitivity(public < internal < private < secret);
|
|
10
|
+
每个调用方(Principal)带 clearance,只能读写 ≤ clearance 的节点。
|
|
11
|
+
③ 硬规则:secret 节点对 clearance < secret 的调用方**写入即拒**(对齐 noema
|
|
12
|
+
「secret 候选自动拒绝」);写入高于自身 clearance 的敏感度 → 拒绝。
|
|
13
|
+
|
|
14
|
+
零第三方依赖。
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import json
|
|
19
|
+
import os
|
|
20
|
+
import time
|
|
21
|
+
import uuid
|
|
22
|
+
|
|
23
|
+
SENSITIVITY_ORDER = ("public", "internal", "private", "secret")
|
|
24
|
+
DEFAULT_SENSITIVITY = "internal"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AccessDenied(Exception):
|
|
28
|
+
"""权限拒绝(读/写/管理)。"""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# 生效条件:形参 level 为模块级常量 SENSITIVITY_ORDER 中的元素时返回其下标,否则抛 AccessDenied。
|
|
32
|
+
def _rank(level: str) -> int:
|
|
33
|
+
try:
|
|
34
|
+
return SENSITIVITY_ORDER.index(level)
|
|
35
|
+
except ValueError:
|
|
36
|
+
raise AccessDenied(f"未知敏感度/密级:{level}") from None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# 生效条件:全部形参均可省略、clearance 默认取模块常量 DEFAULT_SENSITIVITY,构造时先经 _rank(clearance) 校验,随后 session 为假值(含空串)回落为 sess_+uuid 十二位、role 假值回落 "system"、expires_at 为假值(含 0)置 None、layers_allow/ops_allow 为 None 时保持 None 否则转 tuple、theory_ok 经 bool() 转换。
|
|
40
|
+
class Principal:
|
|
41
|
+
"""调用方身份(一次会话一个)。
|
|
42
|
+
|
|
43
|
+
tenant —— 租户(决定根目录)
|
|
44
|
+
actor —— 调用者标识(写入审计)
|
|
45
|
+
clearance —— 最高可读/可写敏感度
|
|
46
|
+
can_write —— 是否允许写
|
|
47
|
+
can_admin —— 是否允许管理操作(forget/restore/review_decide)
|
|
48
|
+
session —— 会话 id(进程/会话模型:每次连接一个)
|
|
49
|
+
harness —— 承载端标识(dsh/zcode/codebuddy…;仅归因,不参与授权)
|
|
50
|
+
unit —— 单元分工(record/reflect/verify/output/sustain;仅归因)
|
|
51
|
+
注:MCP 请求级参数 `as_unit` 会经 `tokens.narrowed_principal`
|
|
52
|
+
产出一次性 Principal——其 role/layers/ops 取自该单元 spec、unit
|
|
53
|
+
记为执行单元。那是**单次调用的临时身份**,不改变本字段的归因
|
|
54
|
+
定位(见 `mcp_server.call_tool`)。
|
|
55
|
+
|
|
56
|
+
令牌扩展(由 `tokens.verify_token` 填充;直接构造时为 None = 不限制):
|
|
57
|
+
role —— 角色(designer/reflection/verifier/recorder/output/sustain/guest)
|
|
58
|
+
token_id —— 令牌 id(可追溯到签发记录)
|
|
59
|
+
parent —— 派生来源令牌 id(权职分离的委派链)
|
|
60
|
+
expires_at —— 过期时间戳(None = 不过期)
|
|
61
|
+
layers_allow —— 可写层白名单(None = 不限制;"*" = 全部)
|
|
62
|
+
ops_allow —— 可执行 op 白名单(同上)
|
|
63
|
+
auth_mode —— direct(直接构造)/ token / legacy_env / anonymous
|
|
64
|
+
|
|
65
|
+
版本层扩展(蜂群互联层0,由 `theory.check` 填充):
|
|
66
|
+
theory_ok —— 版本声明是否合法;False 时**全部写/管理操作被拒**(只读降级)
|
|
67
|
+
theory_version —— 当前声明的协议版本(审计与 whoami 用)
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
# 生效条件:clearance 须为模块级常量 SENSITIVITY_ORDER 成员(否则 _rank 抛 AccessDenied),session 为假值(含 None/空串)时生成 sess_ 随机串,expires_at 为假值(含 None/0)时存 None 否则 float(expires_at),layers_allow/ops_allow 为 None 时存 None 否则 tuple 化。
|
|
71
|
+
def __init__(self, tenant: str = "default", actor: str = "system",
|
|
72
|
+
clearance: str = DEFAULT_SENSITIVITY, can_write: bool = True,
|
|
73
|
+
can_admin: bool = False, session: str = None,
|
|
74
|
+
harness: str = None, unit: str = None,
|
|
75
|
+
role: str = None, token_id: str = None, parent: str = None,
|
|
76
|
+
expires_at: float = None, layers_allow=None, ops_allow=None,
|
|
77
|
+
auth_mode: str = "direct", theory_ok: bool = True,
|
|
78
|
+
theory_version: str = None):
|
|
79
|
+
_rank(clearance) # 校验
|
|
80
|
+
self.tenant = tenant
|
|
81
|
+
self.actor = actor
|
|
82
|
+
self.clearance = clearance
|
|
83
|
+
self.can_write = can_write
|
|
84
|
+
self.can_admin = can_admin
|
|
85
|
+
self.session = session or ("sess_" + uuid.uuid4().hex[:12])
|
|
86
|
+
# 归因维度(嵌套身份):只入审计(_audit/_recent),不参与权限判定。
|
|
87
|
+
# 权限域仍由令牌记录决定(tokens.ROLE_SPECS),与 harness/unit 无关。
|
|
88
|
+
# 受控例外:MCP 请求级 `as_unit` 收窄(tokens.narrowed_principal)产出的是
|
|
89
|
+
# 一次性 Principal,其 role/allow 取自单元 spec——**只做减法**(与 owner
|
|
90
|
+
# 求交 + 管理权恒 False),故不构成本字段「参与授权」的先例。
|
|
91
|
+
self.harness = harness
|
|
92
|
+
self.unit = unit
|
|
93
|
+
self.role = (role or "system")
|
|
94
|
+
self.token_id = token_id
|
|
95
|
+
self.parent = parent
|
|
96
|
+
self.expires_at = float(expires_at) if expires_at else None
|
|
97
|
+
self.layers_allow = None if layers_allow is None else tuple(layers_allow)
|
|
98
|
+
self.ops_allow = None if ops_allow is None else tuple(ops_allow)
|
|
99
|
+
self.auth_mode = auth_mode
|
|
100
|
+
self.theory_ok = bool(theory_ok)
|
|
101
|
+
self.theory_version = theory_version
|
|
102
|
+
|
|
103
|
+
# ---------- 基础判定 ----------
|
|
104
|
+
|
|
105
|
+
# 生效条件:形参 sensitivity 与 self.clearance 均可被 _rank 映射到模块级常量 SENSITIVITY_ORDER 中时,返回前者排名是否不高于后者;任一不在其中则 _rank 抛 AccessDenied。
|
|
106
|
+
def allows(self, sensitivity: str) -> bool:
|
|
107
|
+
"""clearance 是否覆盖该敏感度(可读/可写)。"""
|
|
108
|
+
return _rank(sensitivity) <= _rank(self.clearance)
|
|
109
|
+
|
|
110
|
+
# 生效条件:无 required 形参或模块级常量前置,仅当 self.expires_at(来自 __init__ 的 expires_at)不为 None 且 time.time() 大于它时返回 True,否则返回 False。
|
|
111
|
+
def expired(self) -> bool:
|
|
112
|
+
return self.expires_at is not None and time.time() > self.expires_at
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
# 生效条件:allow 为 None 时返回 True(未声明=不限制),allow 非 None 时返回 "'*' in allow 或 name in allow" 的布尔结果。
|
|
116
|
+
def _in_scope(allow, name: str) -> bool:
|
|
117
|
+
if allow is None: # 未声明 = 不限制(兼容直接构造)
|
|
118
|
+
return True
|
|
119
|
+
return "*" in allow or name in allow
|
|
120
|
+
|
|
121
|
+
# 生效条件:layer 为假值(None/空串)时以 "knowledge" 参与判定,返回 self._in_scope(self.layers_allow, layer or "knowledge") 的结果。
|
|
122
|
+
def allows_layer(self, layer: str) -> bool:
|
|
123
|
+
return self._in_scope(self.layers_allow, layer or "knowledge")
|
|
124
|
+
|
|
125
|
+
# 生效条件:op 为假值(None/空串)时以 "" 参与,先经 strip().lower() 归一化,返回 self._in_scope(self.ops_allow, (op or "").strip().lower()) 的结果。
|
|
126
|
+
def allows_op(self, op: str) -> bool:
|
|
127
|
+
return self._in_scope(self.ops_allow, (op or "").strip().lower())
|
|
128
|
+
|
|
129
|
+
# ---------- 强制校验(越权即 AccessDenied) ----------
|
|
130
|
+
|
|
131
|
+
# 生效条件:无 required 形参或模块级常量前置,当 self.expired()(来自 __init__ 的 expires_at 与当前时间比较)为 True 时抛 AccessDenied,否则无操作返回 None。
|
|
132
|
+
def _require_live(self):
|
|
133
|
+
if self.expired():
|
|
134
|
+
raise AccessDenied(f"actor={self.actor} 令牌已过期")
|
|
135
|
+
|
|
136
|
+
# 生效条件:先调用 self._require_live()(过期则抛 AccessDenied);再要求 self.allows_op(op) 为 True,否则抛 AccessDenied。
|
|
137
|
+
def require_op(self, op: str):
|
|
138
|
+
self._require_live()
|
|
139
|
+
if not self.allows_op(op):
|
|
140
|
+
raise AccessDenied(
|
|
141
|
+
f"角色 {self.role} 无权执行 op={op}(作用域 "
|
|
142
|
+
f"{list(self.ops_allow) if self.ops_allow is not None else '不限'})")
|
|
143
|
+
|
|
144
|
+
# 生效条件:依次要求 self._require_live() 未抛异常、self.theory_ok 为 True、self.can_write 为 True、self.allows(sensitivity) 为 True;任一不满足则抛 AccessDenied。
|
|
145
|
+
def require_write(self, sensitivity: str):
|
|
146
|
+
self._require_live()
|
|
147
|
+
if not self.theory_ok:
|
|
148
|
+
raise AccessDenied(
|
|
149
|
+
"版本层校验未通过(theory_ok=False):全部写操作被拒,"
|
|
150
|
+
"仅保留 theory 修复入口")
|
|
151
|
+
if not self.can_write:
|
|
152
|
+
raise AccessDenied(f"actor={self.actor} 无写权限")
|
|
153
|
+
if not self.allows(sensitivity):
|
|
154
|
+
raise AccessDenied(
|
|
155
|
+
f"写入敏感度 {sensitivity} 超出 clearance {self.clearance}")
|
|
156
|
+
|
|
157
|
+
# 生效条件:先要求 self.require_write(sensitivity) 未抛异常;随后将形参 layer 为假值(None/空串)时按 "knowledge" 处理,并要求 self.allows_layer(layer) 为 True,否则抛 AccessDenied。
|
|
158
|
+
def require_layer_write(self, layer: str, sensitivity: str):
|
|
159
|
+
"""写层校验:密级 + 层白名单双闸门(核心私有内容不可越权修改)。"""
|
|
160
|
+
self.require_write(sensitivity)
|
|
161
|
+
layer = layer or "knowledge"
|
|
162
|
+
if not self.allows_layer(layer):
|
|
163
|
+
raise AccessDenied(
|
|
164
|
+
f"角色 {self.role} 无权写入 {layer} 层"
|
|
165
|
+
f"(可写层 {list(self.layers_allow) if self.layers_allow is not None else '不限'})")
|
|
166
|
+
|
|
167
|
+
# 生效条件:要求 self._require_live() 未抛异常、self.theory_ok 为 True、self.can_admin 为 True 时通过;否则抛 AccessDenied(消息用形参 op 标记操作)。
|
|
168
|
+
def require_admin(self, op: str):
|
|
169
|
+
self._require_live()
|
|
170
|
+
if not self.theory_ok:
|
|
171
|
+
raise AccessDenied(
|
|
172
|
+
f"版本层校验未通过(theory_ok=False):管理操作 {op} 被拒")
|
|
173
|
+
if not self.can_admin:
|
|
174
|
+
raise AccessDenied(f"actor={self.actor} 无管理权限({op})")
|
|
175
|
+
|
|
176
|
+
# 生效条件:无 required 形参或模块级常量前置,返回包含 self 各属性(tenant/actor/clearance/can_write/can_admin/session/harness/unit/role/token_id/parent/auth_mode/expires_at/theory_ok/theory_version 及 layers_allow/ops_allow)的 dict;其中 layers_allow/ops_allow 为 None 时值为 None,否则 list 化。
|
|
177
|
+
def as_dict(self):
|
|
178
|
+
return {"tenant": self.tenant, "actor": self.actor,
|
|
179
|
+
"clearance": self.clearance, "can_write": self.can_write,
|
|
180
|
+
"can_admin": self.can_admin, "session": self.session,
|
|
181
|
+
"harness": self.harness, "unit": self.unit,
|
|
182
|
+
"role": self.role, "token_id": self.token_id,
|
|
183
|
+
"parent": self.parent, "auth_mode": self.auth_mode,
|
|
184
|
+
"expires_at": self.expires_at,
|
|
185
|
+
"theory_ok": self.theory_ok,
|
|
186
|
+
"theory_version": self.theory_version,
|
|
187
|
+
"layers_allow": (None if self.layers_allow is None
|
|
188
|
+
else list(self.layers_allow)),
|
|
189
|
+
"ops_allow": (None if self.ops_allow is None
|
|
190
|
+
else list(self.ops_allow))}
|
|
191
|
+
|
|
192
|
+
# 生效条件:无前置;仅返回 tenant/actor/role/clearance/write/admin 的短摘要用于日志与排障,不含 token、密钥材料与能力白名单明细;
|
|
193
|
+
def __repr__(self):
|
|
194
|
+
return (f"Principal(tenant={self.tenant!r}, actor={self.actor!r}, "
|
|
195
|
+
f"role={self.role!r}, clearance={self.clearance!r}, "
|
|
196
|
+
f"write={self.can_write}, admin={self.can_admin})")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
# 生效条件:path 为 None 时落至 os.path.expanduser("~") 下的 .mdcg/_tenants.json,path 非 None(含空串)时按传入值使用,并在构造内以 self._load() 的返回填充 self.data。
|
|
200
|
+
class TenantRegistry:
|
|
201
|
+
"""租户注册表:tenant → {root, clearance_cap, description}。
|
|
202
|
+
|
|
203
|
+
默认位置:<registry_dir>/_tenants.json(默认 ~/.mdcg/)。
|
|
204
|
+
设计意图:私有租户的 root 指向仓库外目录,开源仓库里只放 public 租户的根。
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
# 生效条件:形参 path 为 None 时取 ~/.mdcg/_tenants.json,否则取 path;self.data 初始化为 _load() 结果(self.path 经 os.path.exists 为真且 JSON 解析为 dict 时取该 dict,否则回落 {"schema":1,"tenants":{}})。
|
|
208
|
+
def __init__(self, path: str = None):
|
|
209
|
+
if path is None:
|
|
210
|
+
path = os.path.join(os.path.expanduser("~"), ".mdcg", "_tenants.json")
|
|
211
|
+
self.path = path
|
|
212
|
+
self.data = self._load()
|
|
213
|
+
|
|
214
|
+
# 生效条件:当 self.path 经 os.path.exists 为真且内容可解析为 dict 时返回该 dict;否则(os.path.exists 为假、非 dict、JSON 解析失败或 OSError)返回 {"schema":1,"tenants":{}}。
|
|
215
|
+
def _load(self):
|
|
216
|
+
if os.path.exists(self.path):
|
|
217
|
+
try:
|
|
218
|
+
with open(self.path, encoding="utf-8") as f:
|
|
219
|
+
d = json.load(f)
|
|
220
|
+
if isinstance(d, dict):
|
|
221
|
+
return d
|
|
222
|
+
except (ValueError, OSError):
|
|
223
|
+
pass
|
|
224
|
+
return {"schema": 1, "tenants": {}}
|
|
225
|
+
|
|
226
|
+
# 生效条件:无 required 形参或模块级常量前置,将 self.data 以 JSON 写入 self.path + ".tmp",随后 os.replace 到 self.path;目录名称为空时用 "." 创建。
|
|
227
|
+
def _save(self):
|
|
228
|
+
os.makedirs(os.path.dirname(self.path) or ".", exist_ok=True)
|
|
229
|
+
tmp = self.path + ".tmp"
|
|
230
|
+
with open(tmp, "w", encoding="utf-8") as f:
|
|
231
|
+
json.dump(self.data, f, ensure_ascii=False, indent=1)
|
|
232
|
+
os.replace(tmp, self.path)
|
|
233
|
+
|
|
234
|
+
# 生效条件:形参 clearance_cap 须为模块级常量 SENSITIVITY_ORDER 成员(否则 _rank 抛 AccessDenied);形参 tenant/root 提供后写入 self.data["tenants"](要求 self.data 含 "tenants" 键,否则 KeyError),_save 成功则返回新登记项。
|
|
235
|
+
def register(self, tenant: str, root: str, clearance_cap: str = DEFAULT_SENSITIVITY,
|
|
236
|
+
description: str = ""):
|
|
237
|
+
_rank(clearance_cap)
|
|
238
|
+
self.data["tenants"][tenant] = {
|
|
239
|
+
"root": os.path.abspath(root),
|
|
240
|
+
"clearance_cap": clearance_cap,
|
|
241
|
+
"description": description,
|
|
242
|
+
"registered_at": time.time(),
|
|
243
|
+
}
|
|
244
|
+
self._save()
|
|
245
|
+
return self.data["tenants"][tenant]
|
|
246
|
+
|
|
247
|
+
# 生效条件:self.data 含 "tenants" 键(否则 KeyError),且该映射中存在形参 tenant 时返回其值,否则返回 None(.get 缺键回落 None,键存在值为 None 也返回 None)。
|
|
248
|
+
def get(self, tenant: str):
|
|
249
|
+
return self.data["tenants"].get(tenant)
|
|
250
|
+
|
|
251
|
+
# 生效条件:self.get(tenant) 返回真值(非 None/空 dict 等)时返回 t["root"](若 t 无 "root" 键则 KeyError);返回假值时返回 None。
|
|
252
|
+
def root_of(self, tenant: str):
|
|
253
|
+
t = self.get(tenant)
|
|
254
|
+
return t["root"] if t else None
|
|
255
|
+
|
|
256
|
+
# 生效条件:self.get(tenant) 返回真值时返回 t["clearance_cap"](缺键则 KeyError);返回假值时返回模块级常量 DEFAULT_SENSITIVITY。
|
|
257
|
+
def cap_of(self, tenant: str):
|
|
258
|
+
t = self.get(tenant)
|
|
259
|
+
return t["clearance_cap"] if t else DEFAULT_SENSITIVITY
|
|
260
|
+
|
|
261
|
+
# 生效条件:self.data 含 "tenants" 键时返回其浅拷贝 dict(self.data["tenants"]);该键缺失时按 self.data["tenants"] 取值会 KeyError,无默认回落。
|
|
262
|
+
def all(self):
|
|
263
|
+
return dict(self.data["tenants"])
|
|
264
|
+
|
|
265
|
+
# 生效条件:cap 由 cap_of(tenant) 决定(形参 tenant 未注册时取模块级常量 DEFAULT_SENSITIVITY);clearance 为假值(含 None/空串)时 want 取 cap,否则先取 clearance,再在 _rank(want) > _rank(cap) 时夹紧为 cap;actor 为假值时取 tenant;返回 Principal(...)。
|
|
266
|
+
def principal_for(self, tenant: str, actor: str = None, clearance: str = None,
|
|
267
|
+
can_write: bool = True, can_admin: bool = False,
|
|
268
|
+
session: str = None) -> Principal:
|
|
269
|
+
"""按租户上限夹紧 clearance(调用方不能超过租户上限)。"""
|
|
270
|
+
cap = self.cap_of(tenant)
|
|
271
|
+
want = clearance or cap
|
|
272
|
+
if _rank(want) > _rank(cap):
|
|
273
|
+
want = cap
|
|
274
|
+
return Principal(tenant=tenant, actor=actor or tenant, clearance=want,
|
|
275
275
|
can_write=can_write, can_admin=can_admin, session=session)
|