pyscoped 0.1.0__tar.gz

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 (392) hide show
  1. pyscoped-0.1.0/.gitignore +34 -0
  2. pyscoped-0.1.0/CLAUDE.md +395 -0
  3. pyscoped-0.1.0/LICENSE +21 -0
  4. pyscoped-0.1.0/PKG-INFO +248 -0
  5. pyscoped-0.1.0/README.md +213 -0
  6. pyscoped-0.1.0/docs/architecture.md +236 -0
  7. pyscoped-0.1.0/docs/extensions/A1-migrations.md +70 -0
  8. pyscoped-0.1.0/docs/extensions/A2-contracts.md +124 -0
  9. pyscoped-0.1.0/docs/extensions/A3-rule-extensions.md +118 -0
  10. pyscoped-0.1.0/docs/extensions/A4-blobs.md +106 -0
  11. pyscoped-0.1.0/docs/extensions/A5-config.md +96 -0
  12. pyscoped-0.1.0/docs/extensions/A6-search.md +91 -0
  13. pyscoped-0.1.0/docs/extensions/A7-templates.md +119 -0
  14. pyscoped-0.1.0/docs/extensions/A8-tiering.md +175 -0
  15. pyscoped-0.1.0/docs/extensions/A9-import-export.md +131 -0
  16. pyscoped-0.1.0/docs/layers/00-compliance.md +203 -0
  17. pyscoped-0.1.0/docs/layers/01-registry.md +165 -0
  18. pyscoped-0.1.0/docs/layers/02-identity.md +122 -0
  19. pyscoped-0.1.0/docs/layers/03-objects.md +150 -0
  20. pyscoped-0.1.0/docs/layers/04-tenancy.md +148 -0
  21. pyscoped-0.1.0/docs/layers/05-rules.md +188 -0
  22. pyscoped-0.1.0/docs/layers/06-audit.md +139 -0
  23. pyscoped-0.1.0/docs/layers/07-temporal.md +90 -0
  24. pyscoped-0.1.0/docs/layers/08-environments.md +174 -0
  25. pyscoped-0.1.0/docs/layers/09-flow.md +193 -0
  26. pyscoped-0.1.0/docs/layers/10-deployments.md +138 -0
  27. pyscoped-0.1.0/docs/layers/11-secrets.md +212 -0
  28. pyscoped-0.1.0/docs/layers/12-integrations.md +216 -0
  29. pyscoped-0.1.0/docs/layers/13-connector.md +273 -0
  30. pyscoped-0.1.0/docs/layers/14-events.md +183 -0
  31. pyscoped-0.1.0/docs/layers/15-notifications.md +173 -0
  32. pyscoped-0.1.0/docs/layers/16-scheduling.md +165 -0
  33. pyscoped-0.1.0/examples/django_project/.gitignore +4 -0
  34. pyscoped-0.1.0/examples/django_project/README.md +188 -0
  35. pyscoped-0.1.0/examples/django_project/core/__init__.py +0 -0
  36. pyscoped-0.1.0/examples/django_project/core/context_processors.py +44 -0
  37. pyscoped-0.1.0/examples/django_project/core/management/__init__.py +0 -0
  38. pyscoped-0.1.0/examples/django_project/core/management/commands/__init__.py +0 -0
  39. pyscoped-0.1.0/examples/django_project/core/management/commands/seed_demo.py +464 -0
  40. pyscoped-0.1.0/examples/django_project/core/middleware.py +29 -0
  41. pyscoped-0.1.0/examples/django_project/core/migrations/0001_initial.py +28 -0
  42. pyscoped-0.1.0/examples/django_project/core/migrations/__init__.py +0 -0
  43. pyscoped-0.1.0/examples/django_project/core/models.py +25 -0
  44. pyscoped-0.1.0/examples/django_project/core/services.py +151 -0
  45. pyscoped-0.1.0/examples/django_project/core/templatetags/__init__.py +0 -0
  46. pyscoped-0.1.0/examples/django_project/core/templatetags/scoped_tags.py +189 -0
  47. pyscoped-0.1.0/examples/django_project/core/views.py +18 -0
  48. pyscoped-0.1.0/examples/django_project/db.sqlite3 +0 -0
  49. pyscoped-0.1.0/examples/django_project/launchpad/__init__.py +0 -0
  50. pyscoped-0.1.0/examples/django_project/launchpad/settings.py +96 -0
  51. pyscoped-0.1.0/examples/django_project/launchpad/urls.py +15 -0
  52. pyscoped-0.1.0/examples/django_project/launchpad/wsgi.py +7 -0
  53. pyscoped-0.1.0/examples/django_project/manage.py +21 -0
  54. pyscoped-0.1.0/examples/django_project/requirements.txt +3 -0
  55. pyscoped-0.1.0/examples/django_project/static/css/custom.css +53 -0
  56. pyscoped-0.1.0/examples/django_project/static/js/app.js +38 -0
  57. pyscoped-0.1.0/examples/django_project/templates/audit/detail.html +110 -0
  58. pyscoped-0.1.0/examples/django_project/templates/audit/list.html +90 -0
  59. pyscoped-0.1.0/examples/django_project/templates/base.html +67 -0
  60. pyscoped-0.1.0/examples/django_project/templates/components/_data_table.html +15 -0
  61. pyscoped-0.1.0/examples/django_project/templates/components/_empty_state.html +11 -0
  62. pyscoped-0.1.0/examples/django_project/templates/components/_header.html +19 -0
  63. pyscoped-0.1.0/examples/django_project/templates/components/_modal.html +13 -0
  64. pyscoped-0.1.0/examples/django_project/templates/components/_pagination.html +16 -0
  65. pyscoped-0.1.0/examples/django_project/templates/components/_sidebar.html +147 -0
  66. pyscoped-0.1.0/examples/django_project/templates/components/_stat_card.html +9 -0
  67. pyscoped-0.1.0/examples/django_project/templates/components/_state_badge.html +13 -0
  68. pyscoped-0.1.0/examples/django_project/templates/components/_tabs.html +13 -0
  69. pyscoped-0.1.0/examples/django_project/templates/components/_timeline.html +31 -0
  70. pyscoped-0.1.0/examples/django_project/templates/components/_toast.html +7 -0
  71. pyscoped-0.1.0/examples/django_project/templates/components/_user_switcher.html +26 -0
  72. pyscoped-0.1.0/examples/django_project/templates/config/list.html +105 -0
  73. pyscoped-0.1.0/examples/django_project/templates/connectors/list.html +64 -0
  74. pyscoped-0.1.0/examples/django_project/templates/dashboard/index.html +67 -0
  75. pyscoped-0.1.0/examples/django_project/templates/deployments/detail.html +70 -0
  76. pyscoped-0.1.0/examples/django_project/templates/deployments/list.html +97 -0
  77. pyscoped-0.1.0/examples/django_project/templates/environments/detail.html +109 -0
  78. pyscoped-0.1.0/examples/django_project/templates/environments/list.html +100 -0
  79. pyscoped-0.1.0/examples/django_project/templates/events/list.html +62 -0
  80. pyscoped-0.1.0/examples/django_project/templates/flags/list.html +60 -0
  81. pyscoped-0.1.0/examples/django_project/templates/health/index.html +147 -0
  82. pyscoped-0.1.0/examples/django_project/templates/integrations/list.html +95 -0
  83. pyscoped-0.1.0/examples/django_project/templates/notifications/list.html +69 -0
  84. pyscoped-0.1.0/examples/django_project/templates/pipelines/list.html +72 -0
  85. pyscoped-0.1.0/examples/django_project/templates/registration/login.html +72 -0
  86. pyscoped-0.1.0/examples/django_project/templates/rules/list.html +89 -0
  87. pyscoped-0.1.0/examples/django_project/templates/scheduling/list.html +153 -0
  88. pyscoped-0.1.0/examples/django_project/templates/secrets/list.html +112 -0
  89. pyscoped-0.1.0/examples/django_project/templates/services/create.html +53 -0
  90. pyscoped-0.1.0/examples/django_project/templates/services/detail.html +144 -0
  91. pyscoped-0.1.0/examples/django_project/templates/services/list.html +62 -0
  92. pyscoped-0.1.0/examples/django_project/templates/services/search.html +83 -0
  93. pyscoped-0.1.0/examples/django_project/templates/teams/detail.html +101 -0
  94. pyscoped-0.1.0/examples/django_project/templates/teams/list.html +31 -0
  95. pyscoped-0.1.0/examples/django_project/templates/templates_page/list.html +57 -0
  96. pyscoped-0.1.0/examples/django_project/webapp/__init__.py +0 -0
  97. pyscoped-0.1.0/examples/django_project/webapp/forms.py +1 -0
  98. pyscoped-0.1.0/examples/django_project/webapp/urls.py +97 -0
  99. pyscoped-0.1.0/examples/django_project/webapp/views/__init__.py +0 -0
  100. pyscoped-0.1.0/examples/django_project/webapp/views/audit.py +120 -0
  101. pyscoped-0.1.0/examples/django_project/webapp/views/config.py +111 -0
  102. pyscoped-0.1.0/examples/django_project/webapp/views/connectors.py +37 -0
  103. pyscoped-0.1.0/examples/django_project/webapp/views/dashboard.py +68 -0
  104. pyscoped-0.1.0/examples/django_project/webapp/views/deployments.py +76 -0
  105. pyscoped-0.1.0/examples/django_project/webapp/views/environments.py +97 -0
  106. pyscoped-0.1.0/examples/django_project/webapp/views/events.py +36 -0
  107. pyscoped-0.1.0/examples/django_project/webapp/views/flags.py +56 -0
  108. pyscoped-0.1.0/examples/django_project/webapp/views/health.py +85 -0
  109. pyscoped-0.1.0/examples/django_project/webapp/views/integrations.py +58 -0
  110. pyscoped-0.1.0/examples/django_project/webapp/views/notifications.py +67 -0
  111. pyscoped-0.1.0/examples/django_project/webapp/views/pipelines.py +40 -0
  112. pyscoped-0.1.0/examples/django_project/webapp/views/rules.py +49 -0
  113. pyscoped-0.1.0/examples/django_project/webapp/views/scheduling.py +62 -0
  114. pyscoped-0.1.0/examples/django_project/webapp/views/search.py +57 -0
  115. pyscoped-0.1.0/examples/django_project/webapp/views/secrets.py +84 -0
  116. pyscoped-0.1.0/examples/django_project/webapp/views/services.py +183 -0
  117. pyscoped-0.1.0/examples/django_project/webapp/views/teams.py +95 -0
  118. pyscoped-0.1.0/examples/django_project/webapp/views/templates.py +86 -0
  119. pyscoped-0.1.0/pyproject.toml +50 -0
  120. pyscoped-0.1.0/scoped/__init__.py +3 -0
  121. pyscoped-0.1.0/scoped/audit/__init__.py +17 -0
  122. pyscoped-0.1.0/scoped/audit/models.py +88 -0
  123. pyscoped-0.1.0/scoped/audit/query.py +287 -0
  124. pyscoped-0.1.0/scoped/audit/writer.py +227 -0
  125. pyscoped-0.1.0/scoped/conf.py +54 -0
  126. pyscoped-0.1.0/scoped/connector/__init__.py +42 -0
  127. pyscoped-0.1.0/scoped/connector/bridge.py +452 -0
  128. pyscoped-0.1.0/scoped/connector/marketplace/__init__.py +21 -0
  129. pyscoped-0.1.0/scoped/connector/marketplace/discovery.py +196 -0
  130. pyscoped-0.1.0/scoped/connector/marketplace/models.py +151 -0
  131. pyscoped-0.1.0/scoped/connector/marketplace/publishing.py +236 -0
  132. pyscoped-0.1.0/scoped/connector/models.py +210 -0
  133. pyscoped-0.1.0/scoped/connector/protocol.py +192 -0
  134. pyscoped-0.1.0/scoped/contrib/__init__.py +1 -0
  135. pyscoped-0.1.0/scoped/contrib/_base.py +45 -0
  136. pyscoped-0.1.0/scoped/contrib/django/__init__.py +47 -0
  137. pyscoped-0.1.0/scoped/contrib/django/apps.py +22 -0
  138. pyscoped-0.1.0/scoped/contrib/django/backend.py +189 -0
  139. pyscoped-0.1.0/scoped/contrib/django/management/__init__.py +0 -0
  140. pyscoped-0.1.0/scoped/contrib/django/management/commands/__init__.py +0 -0
  141. pyscoped-0.1.0/scoped/contrib/django/management/commands/scoped_audit.py +46 -0
  142. pyscoped-0.1.0/scoped/contrib/django/management/commands/scoped_compliance.py +34 -0
  143. pyscoped-0.1.0/scoped/contrib/django/management/commands/scoped_health.py +25 -0
  144. pyscoped-0.1.0/scoped/contrib/django/middleware.py +90 -0
  145. pyscoped-0.1.0/scoped/contrib/fastapi/__init__.py +50 -0
  146. pyscoped-0.1.0/scoped/contrib/fastapi/dependencies.py +36 -0
  147. pyscoped-0.1.0/scoped/contrib/fastapi/middleware.py +75 -0
  148. pyscoped-0.1.0/scoped/contrib/fastapi/router.py +47 -0
  149. pyscoped-0.1.0/scoped/contrib/fastapi/schemas.py +101 -0
  150. pyscoped-0.1.0/scoped/contrib/flask/__init__.py +29 -0
  151. pyscoped-0.1.0/scoped/contrib/flask/admin.py +55 -0
  152. pyscoped-0.1.0/scoped/contrib/flask/extension.py +101 -0
  153. pyscoped-0.1.0/scoped/contrib/mcp/__init__.py +26 -0
  154. pyscoped-0.1.0/scoped/contrib/mcp/resources.py +58 -0
  155. pyscoped-0.1.0/scoped/contrib/mcp/server.py +35 -0
  156. pyscoped-0.1.0/scoped/contrib/mcp/tools.py +102 -0
  157. pyscoped-0.1.0/scoped/deployments/__init__.py +29 -0
  158. pyscoped-0.1.0/scoped/deployments/executor.py +294 -0
  159. pyscoped-0.1.0/scoped/deployments/gates.py +113 -0
  160. pyscoped-0.1.0/scoped/deployments/models.py +171 -0
  161. pyscoped-0.1.0/scoped/deployments/rollback.py +107 -0
  162. pyscoped-0.1.0/scoped/environments/__init__.py +29 -0
  163. pyscoped-0.1.0/scoped/environments/container.py +174 -0
  164. pyscoped-0.1.0/scoped/environments/lifecycle.py +365 -0
  165. pyscoped-0.1.0/scoped/environments/models.py +234 -0
  166. pyscoped-0.1.0/scoped/environments/snapshot.py +148 -0
  167. pyscoped-0.1.0/scoped/events/__init__.py +36 -0
  168. pyscoped-0.1.0/scoped/events/bus.py +229 -0
  169. pyscoped-0.1.0/scoped/events/models.py +223 -0
  170. pyscoped-0.1.0/scoped/events/subscriptions.py +196 -0
  171. pyscoped-0.1.0/scoped/events/webhooks.py +214 -0
  172. pyscoped-0.1.0/scoped/exceptions.py +376 -0
  173. pyscoped-0.1.0/scoped/flow/__init__.py +30 -0
  174. pyscoped-0.1.0/scoped/flow/engine.py +217 -0
  175. pyscoped-0.1.0/scoped/flow/models.py +221 -0
  176. pyscoped-0.1.0/scoped/flow/pipeline.py +264 -0
  177. pyscoped-0.1.0/scoped/flow/promotion.py +152 -0
  178. pyscoped-0.1.0/scoped/identity/__init__.py +22 -0
  179. pyscoped-0.1.0/scoped/identity/context.py +93 -0
  180. pyscoped-0.1.0/scoped/identity/principal.py +357 -0
  181. pyscoped-0.1.0/scoped/identity/resolver.py +223 -0
  182. pyscoped-0.1.0/scoped/integrations/__init__.py +35 -0
  183. pyscoped-0.1.0/scoped/integrations/connectors.py +168 -0
  184. pyscoped-0.1.0/scoped/integrations/hooks.py +275 -0
  185. pyscoped-0.1.0/scoped/integrations/lifecycle.py +291 -0
  186. pyscoped-0.1.0/scoped/integrations/models.py +233 -0
  187. pyscoped-0.1.0/scoped/integrations/sandbox.py +141 -0
  188. pyscoped-0.1.0/scoped/notifications/__init__.py +34 -0
  189. pyscoped-0.1.0/scoped/notifications/delivery.py +75 -0
  190. pyscoped-0.1.0/scoped/notifications/engine.py +278 -0
  191. pyscoped-0.1.0/scoped/notifications/models.py +164 -0
  192. pyscoped-0.1.0/scoped/notifications/preferences.py +118 -0
  193. pyscoped-0.1.0/scoped/objects/__init__.py +34 -0
  194. pyscoped-0.1.0/scoped/objects/blobs.py +441 -0
  195. pyscoped-0.1.0/scoped/objects/export.py +242 -0
  196. pyscoped-0.1.0/scoped/objects/import_.py +168 -0
  197. pyscoped-0.1.0/scoped/objects/isolation.py +12 -0
  198. pyscoped-0.1.0/scoped/objects/manager.py +460 -0
  199. pyscoped-0.1.0/scoped/objects/models.py +91 -0
  200. pyscoped-0.1.0/scoped/objects/search.py +384 -0
  201. pyscoped-0.1.0/scoped/objects/versioning.py +32 -0
  202. pyscoped-0.1.0/scoped/registry/__init__.py +48 -0
  203. pyscoped-0.1.0/scoped/registry/base.py +374 -0
  204. pyscoped-0.1.0/scoped/registry/contracts.py +637 -0
  205. pyscoped-0.1.0/scoped/registry/decorators.py +138 -0
  206. pyscoped-0.1.0/scoped/registry/introspection.py +133 -0
  207. pyscoped-0.1.0/scoped/registry/kinds.py +101 -0
  208. pyscoped-0.1.0/scoped/registry/sqlite_store.py +105 -0
  209. pyscoped-0.1.0/scoped/registry/store.py +125 -0
  210. pyscoped-0.1.0/scoped/registry/templates.py +418 -0
  211. pyscoped-0.1.0/scoped/rules/__init__.py +53 -0
  212. pyscoped-0.1.0/scoped/rules/builtins.py +311 -0
  213. pyscoped-0.1.0/scoped/rules/compiler.py +121 -0
  214. pyscoped-0.1.0/scoped/rules/engine.py +535 -0
  215. pyscoped-0.1.0/scoped/rules/features.py +183 -0
  216. pyscoped-0.1.0/scoped/rules/models.py +213 -0
  217. pyscoped-0.1.0/scoped/rules/quotas.py +222 -0
  218. pyscoped-0.1.0/scoped/rules/rate_limit.py +190 -0
  219. pyscoped-0.1.0/scoped/rules/redaction.py +192 -0
  220. pyscoped-0.1.0/scoped/scheduling/__init__.py +27 -0
  221. pyscoped-0.1.0/scoped/scheduling/models.py +158 -0
  222. pyscoped-0.1.0/scoped/scheduling/queue.py +184 -0
  223. pyscoped-0.1.0/scoped/scheduling/scheduler.py +202 -0
  224. pyscoped-0.1.0/scoped/secrets/__init__.py +36 -0
  225. pyscoped-0.1.0/scoped/secrets/backend.py +107 -0
  226. pyscoped-0.1.0/scoped/secrets/leak_detection.py +105 -0
  227. pyscoped-0.1.0/scoped/secrets/models.py +273 -0
  228. pyscoped-0.1.0/scoped/secrets/policy.py +137 -0
  229. pyscoped-0.1.0/scoped/secrets/vault.py +517 -0
  230. pyscoped-0.1.0/scoped/storage/__init__.py +47 -0
  231. pyscoped-0.1.0/scoped/storage/archival.py +326 -0
  232. pyscoped-0.1.0/scoped/storage/blobs.py +129 -0
  233. pyscoped-0.1.0/scoped/storage/interface.py +132 -0
  234. pyscoped-0.1.0/scoped/storage/migrations/__init__.py +17 -0
  235. pyscoped-0.1.0/scoped/storage/migrations/base.py +42 -0
  236. pyscoped-0.1.0/scoped/storage/migrations/registry.py +113 -0
  237. pyscoped-0.1.0/scoped/storage/migrations/runner.py +253 -0
  238. pyscoped-0.1.0/scoped/storage/migrations/versions/__init__.py +8 -0
  239. pyscoped-0.1.0/scoped/storage/migrations/versions/m0001_initial_schema.py +799 -0
  240. pyscoped-0.1.0/scoped/storage/migrations/versions/m0002_contracts.py +67 -0
  241. pyscoped-0.1.0/scoped/storage/migrations/versions/m0003_blobs.py +73 -0
  242. pyscoped-0.1.0/scoped/storage/migrations/versions/m0004_scope_settings.py +50 -0
  243. pyscoped-0.1.0/scoped/storage/migrations/versions/m0005_search_index.py +57 -0
  244. pyscoped-0.1.0/scoped/storage/migrations/versions/m0006_templates.py +69 -0
  245. pyscoped-0.1.0/scoped/storage/migrations/versions/m0007_tiering_archival.py +93 -0
  246. pyscoped-0.1.0/scoped/storage/migrations/versions/m0008_events_webhooks.py +88 -0
  247. pyscoped-0.1.0/scoped/storage/migrations/versions/m0009_notifications.py +72 -0
  248. pyscoped-0.1.0/scoped/storage/migrations/versions/m0010_scheduling.py +73 -0
  249. pyscoped-0.1.0/scoped/storage/sqlite.py +1267 -0
  250. pyscoped-0.1.0/scoped/storage/tiering.py +423 -0
  251. pyscoped-0.1.0/scoped/temporal/__init__.py +16 -0
  252. pyscoped-0.1.0/scoped/temporal/constraints.py +146 -0
  253. pyscoped-0.1.0/scoped/temporal/reconstruction.py +131 -0
  254. pyscoped-0.1.0/scoped/temporal/rollback.py +359 -0
  255. pyscoped-0.1.0/scoped/tenancy/__init__.py +37 -0
  256. pyscoped-0.1.0/scoped/tenancy/config.py +419 -0
  257. pyscoped-0.1.0/scoped/tenancy/engine.py +233 -0
  258. pyscoped-0.1.0/scoped/tenancy/lifecycle.py +411 -0
  259. pyscoped-0.1.0/scoped/tenancy/models.py +208 -0
  260. pyscoped-0.1.0/scoped/tenancy/projection.py +203 -0
  261. pyscoped-0.1.0/scoped/testing/__init__.py +26 -0
  262. pyscoped-0.1.0/scoped/testing/auditor.py +244 -0
  263. pyscoped-0.1.0/scoped/testing/base.py +192 -0
  264. pyscoped-0.1.0/scoped/testing/fuzzer.py +278 -0
  265. pyscoped-0.1.0/scoped/testing/health.py +173 -0
  266. pyscoped-0.1.0/scoped/testing/introspection.py +147 -0
  267. pyscoped-0.1.0/scoped/testing/middleware.py +265 -0
  268. pyscoped-0.1.0/scoped/testing/reports.py +146 -0
  269. pyscoped-0.1.0/scoped/testing/rollback.py +247 -0
  270. pyscoped-0.1.0/scoped/types.py +217 -0
  271. pyscoped-0.1.0/tests/__init__.py +0 -0
  272. pyscoped-0.1.0/tests/conftest.py +32 -0
  273. pyscoped-0.1.0/tests/test_audit/__init__.py +0 -0
  274. pyscoped-0.1.0/tests/test_audit/test_models.py +100 -0
  275. pyscoped-0.1.0/tests/test_audit/test_query.py +189 -0
  276. pyscoped-0.1.0/tests/test_audit/test_writer.py +149 -0
  277. pyscoped-0.1.0/tests/test_compliance/__init__.py +0 -0
  278. pyscoped-0.1.0/tests/test_compliance/test_auditor.py +226 -0
  279. pyscoped-0.1.0/tests/test_compliance/test_base.py +180 -0
  280. pyscoped-0.1.0/tests/test_compliance/test_fuzzer.py +101 -0
  281. pyscoped-0.1.0/tests/test_compliance/test_health.py +123 -0
  282. pyscoped-0.1.0/tests/test_compliance/test_introspection.py +135 -0
  283. pyscoped-0.1.0/tests/test_compliance/test_middleware.py +238 -0
  284. pyscoped-0.1.0/tests/test_compliance/test_reports.py +123 -0
  285. pyscoped-0.1.0/tests/test_compliance/test_rollback.py +71 -0
  286. pyscoped-0.1.0/tests/test_connector/__init__.py +0 -0
  287. pyscoped-0.1.0/tests/test_connector/test_bridge.py +412 -0
  288. pyscoped-0.1.0/tests/test_connector/test_marketplace.py +434 -0
  289. pyscoped-0.1.0/tests/test_connector/test_models.py +227 -0
  290. pyscoped-0.1.0/tests/test_connector/test_protocol.py +186 -0
  291. pyscoped-0.1.0/tests/test_contrib/__init__.py +0 -0
  292. pyscoped-0.1.0/tests/test_contrib/conftest.py +23 -0
  293. pyscoped-0.1.0/tests/test_contrib/test_django/__init__.py +0 -0
  294. pyscoped-0.1.0/tests/test_contrib/test_django/conftest.py +15 -0
  295. pyscoped-0.1.0/tests/test_contrib/test_django/settings.py +23 -0
  296. pyscoped-0.1.0/tests/test_contrib/test_django/test_backend.py +185 -0
  297. pyscoped-0.1.0/tests/test_contrib/test_django/test_commands.py +101 -0
  298. pyscoped-0.1.0/tests/test_contrib/test_django/test_middleware.py +138 -0
  299. pyscoped-0.1.0/tests/test_contrib/test_django/urls.py +14 -0
  300. pyscoped-0.1.0/tests/test_contrib/test_fastapi/__init__.py +0 -0
  301. pyscoped-0.1.0/tests/test_contrib/test_fastapi/conftest.py +54 -0
  302. pyscoped-0.1.0/tests/test_contrib/test_fastapi/test_dependencies.py +84 -0
  303. pyscoped-0.1.0/tests/test_contrib/test_fastapi/test_middleware.py +34 -0
  304. pyscoped-0.1.0/tests/test_contrib/test_fastapi/test_router.py +81 -0
  305. pyscoped-0.1.0/tests/test_contrib/test_fastapi/test_schemas.py +105 -0
  306. pyscoped-0.1.0/tests/test_contrib/test_flask/__init__.py +0 -0
  307. pyscoped-0.1.0/tests/test_contrib/test_flask/conftest.py +53 -0
  308. pyscoped-0.1.0/tests/test_contrib/test_flask/test_extension.py +101 -0
  309. pyscoped-0.1.0/tests/test_contrib/test_mcp/__init__.py +0 -0
  310. pyscoped-0.1.0/tests/test_contrib/test_mcp/conftest.py +36 -0
  311. pyscoped-0.1.0/tests/test_contrib/test_mcp/test_resources.py +55 -0
  312. pyscoped-0.1.0/tests/test_contrib/test_mcp/test_tools.py +104 -0
  313. pyscoped-0.1.0/tests/test_deployments/__init__.py +0 -0
  314. pyscoped-0.1.0/tests/test_deployments/test_executor.py +237 -0
  315. pyscoped-0.1.0/tests/test_deployments/test_gates.py +136 -0
  316. pyscoped-0.1.0/tests/test_deployments/test_models.py +134 -0
  317. pyscoped-0.1.0/tests/test_deployments/test_rollback.py +124 -0
  318. pyscoped-0.1.0/tests/test_environments/__init__.py +0 -0
  319. pyscoped-0.1.0/tests/test_environments/test_container.py +144 -0
  320. pyscoped-0.1.0/tests/test_environments/test_lifecycle.py +267 -0
  321. pyscoped-0.1.0/tests/test_environments/test_models.py +165 -0
  322. pyscoped-0.1.0/tests/test_environments/test_snapshot.py +127 -0
  323. pyscoped-0.1.0/tests/test_events/__init__.py +0 -0
  324. pyscoped-0.1.0/tests/test_events/test_bus.py +307 -0
  325. pyscoped-0.1.0/tests/test_events/test_models.py +194 -0
  326. pyscoped-0.1.0/tests/test_events/test_subscriptions.py +247 -0
  327. pyscoped-0.1.0/tests/test_events/test_webhooks.py +225 -0
  328. pyscoped-0.1.0/tests/test_flow/__init__.py +0 -0
  329. pyscoped-0.1.0/tests/test_flow/test_engine.py +264 -0
  330. pyscoped-0.1.0/tests/test_flow/test_models.py +152 -0
  331. pyscoped-0.1.0/tests/test_flow/test_pipeline.py +227 -0
  332. pyscoped-0.1.0/tests/test_flow/test_promotion.py +241 -0
  333. pyscoped-0.1.0/tests/test_identity/__init__.py +0 -0
  334. pyscoped-0.1.0/tests/test_identity/test_context.py +105 -0
  335. pyscoped-0.1.0/tests/test_identity/test_principal.py +208 -0
  336. pyscoped-0.1.0/tests/test_identity/test_resolver.py +138 -0
  337. pyscoped-0.1.0/tests/test_integrations/__init__.py +0 -0
  338. pyscoped-0.1.0/tests/test_integrations/test_connectors.py +167 -0
  339. pyscoped-0.1.0/tests/test_integrations/test_hooks.py +323 -0
  340. pyscoped-0.1.0/tests/test_integrations/test_lifecycle.py +272 -0
  341. pyscoped-0.1.0/tests/test_integrations/test_models.py +179 -0
  342. pyscoped-0.1.0/tests/test_integrations/test_sandbox.py +177 -0
  343. pyscoped-0.1.0/tests/test_notifications/__init__.py +0 -0
  344. pyscoped-0.1.0/tests/test_notifications/test_notifications.py +540 -0
  345. pyscoped-0.1.0/tests/test_objects/__init__.py +0 -0
  346. pyscoped-0.1.0/tests/test_objects/test_blobs.py +455 -0
  347. pyscoped-0.1.0/tests/test_objects/test_import_export.py +479 -0
  348. pyscoped-0.1.0/tests/test_objects/test_isolation.py +16 -0
  349. pyscoped-0.1.0/tests/test_objects/test_manager.py +392 -0
  350. pyscoped-0.1.0/tests/test_objects/test_models.py +117 -0
  351. pyscoped-0.1.0/tests/test_objects/test_search.py +507 -0
  352. pyscoped-0.1.0/tests/test_objects/test_versioning.py +52 -0
  353. pyscoped-0.1.0/tests/test_registry/__init__.py +0 -0
  354. pyscoped-0.1.0/tests/test_registry/test_base.py +219 -0
  355. pyscoped-0.1.0/tests/test_registry/test_contracts.py +681 -0
  356. pyscoped-0.1.0/tests/test_registry/test_decorators.py +79 -0
  357. pyscoped-0.1.0/tests/test_registry/test_introspection.py +88 -0
  358. pyscoped-0.1.0/tests/test_registry/test_storage_backend.py +135 -0
  359. pyscoped-0.1.0/tests/test_registry/test_store.py +115 -0
  360. pyscoped-0.1.0/tests/test_registry/test_templates.py +579 -0
  361. pyscoped-0.1.0/tests/test_rules/__init__.py +0 -0
  362. pyscoped-0.1.0/tests/test_rules/test_builtins.py +97 -0
  363. pyscoped-0.1.0/tests/test_rules/test_compiler.py +106 -0
  364. pyscoped-0.1.0/tests/test_rules/test_engine.py +444 -0
  365. pyscoped-0.1.0/tests/test_rules/test_features.py +234 -0
  366. pyscoped-0.1.0/tests/test_rules/test_models.py +109 -0
  367. pyscoped-0.1.0/tests/test_rules/test_quotas.py +309 -0
  368. pyscoped-0.1.0/tests/test_rules/test_rate_limit.py +284 -0
  369. pyscoped-0.1.0/tests/test_rules/test_redaction.py +264 -0
  370. pyscoped-0.1.0/tests/test_scheduling/__init__.py +0 -0
  371. pyscoped-0.1.0/tests/test_scheduling/test_scheduling.py +425 -0
  372. pyscoped-0.1.0/tests/test_secrets/__init__.py +0 -0
  373. pyscoped-0.1.0/tests/test_secrets/test_backend.py +79 -0
  374. pyscoped-0.1.0/tests/test_secrets/test_leak_detection.py +136 -0
  375. pyscoped-0.1.0/tests/test_secrets/test_models.py +136 -0
  376. pyscoped-0.1.0/tests/test_secrets/test_policy.py +179 -0
  377. pyscoped-0.1.0/tests/test_secrets/test_vault.py +386 -0
  378. pyscoped-0.1.0/tests/test_storage/__init__.py +0 -0
  379. pyscoped-0.1.0/tests/test_storage/test_archival.py +344 -0
  380. pyscoped-0.1.0/tests/test_storage/test_blobs_backend.py +135 -0
  381. pyscoped-0.1.0/tests/test_storage/test_migrations.py +431 -0
  382. pyscoped-0.1.0/tests/test_storage/test_tiering.py +457 -0
  383. pyscoped-0.1.0/tests/test_temporal/__init__.py +0 -0
  384. pyscoped-0.1.0/tests/test_temporal/test_constraints.py +197 -0
  385. pyscoped-0.1.0/tests/test_temporal/test_reconstruction.py +189 -0
  386. pyscoped-0.1.0/tests/test_temporal/test_rollback.py +447 -0
  387. pyscoped-0.1.0/tests/test_tenancy/__init__.py +0 -0
  388. pyscoped-0.1.0/tests/test_tenancy/test_config.py +478 -0
  389. pyscoped-0.1.0/tests/test_tenancy/test_engine.py +214 -0
  390. pyscoped-0.1.0/tests/test_tenancy/test_lifecycle.py +247 -0
  391. pyscoped-0.1.0/tests/test_tenancy/test_models.py +94 -0
  392. pyscoped-0.1.0/tests/test_tenancy/test_projection.py +166 -0
@@ -0,0 +1,34 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ *.egg
9
+
10
+ # Virtual environments
11
+ .venv/
12
+ venv/
13
+ env/
14
+
15
+ # IDE
16
+ .idea/
17
+ .vscode/
18
+ *.swp
19
+ *.swo
20
+ *~
21
+
22
+ # OS
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Testing
27
+ .pytest_cache/
28
+ .coverage
29
+ htmlcov/
30
+ .tox/
31
+
32
+ # Distribution
33
+ *.tar.gz
34
+ *.whl
@@ -0,0 +1,395 @@
1
+ # Scoped — Agent Instructions
2
+
3
+ ## What This Is
4
+
5
+ Scoped is a universal object-isolation and tenancy framework for Python. It guarantees that anything built on it can be isolated, shared, traced, and rolled back — to any degree, at any time, by anyone with the right to do so.
6
+
7
+ **Repository:** https://github.com/kwip-info/scoped
8
+ **Python:** 3.11+ (developed on 3.13)
9
+ **Dependencies:** None required (SQLite backend included)
10
+
11
+ ## Architecture
12
+
13
+ 16 layers + a compliance engine (Layer 0). Every layer depends on the layers below it.
14
+
15
+ | Layer | Module | Purpose |
16
+ |-------|--------|---------|
17
+ | 0 | `scoped.testing` | Compliance engine — validates all invariants |
18
+ | 1 | `scoped.registry` | Universal construct registration (URNs) |
19
+ | 2 | `scoped.identity` | Generic principal machinery + ScopedContext |
20
+ | 3 | `scoped.objects` | Versioned, isolated data objects |
21
+ | 4 | `scoped.tenancy` | Scopes, membership, projection (the sharing primitive) |
22
+ | 5 | `scoped.rules` | Deny-overrides policy engine |
23
+ | 6 | `scoped.audit` | Hash-chained, immutable, append-only trace |
24
+ | 7 | `scoped.temporal` | Point-in-time reconstruction + cascading rollback |
25
+ | 8 | `scoped.environments` | Ephemeral workspaces |
26
+ | 9 | `scoped.flow` | Stages, pipelines, flow channels, promotions |
27
+ | 10 | `scoped.deployments` | Graduation to external targets with gate checks |
28
+ | 11 | `scoped.secrets` | Encrypted vault with ref-based zero-trust access |
29
+ | 12 | `scoped.integrations` | Sandboxed plugins, hooks, external systems |
30
+ | 13 | `scoped.connector` | Cross-org meshing, federation, marketplace |
31
+ | 14 | `scoped.events` | Asynchronous scoped event bus + webhooks |
32
+ | 15 | `scoped.notifications` | Principal-targeted messages from events/rules |
33
+ | 16 | `scoped.scheduling` | Recurring schedules, scoped job execution |
34
+
35
+ 9 extensions enrich existing layers: A1 (Migrations), A2 (Contracts), A3 (Rule Extensions), A4 (Blobs), A5 (Config Hierarchy), A6 (Search), A7 (Templates), A8 (Tiering), A9 (Import/Export).
36
+
37
+ ## The 10 Invariants
38
+
39
+ These are absolute. Never write code that violates them.
40
+
41
+ 1. **Nothing exists without registration.** Every construct must have a registry entry with a URN.
42
+ 2. **Nothing happens without identity.** Every operation requires a `ScopedContext` with an acting principal.
43
+ 3. **Nothing is shared by default.** Every object starts creator-private. Sharing is always explicit via scope projection.
44
+ 4. **Nothing happens without a trace.** Every action produces an immutable, hash-chained audit entry.
45
+ 5. **Nothing is truly deleted.** Objects are tombstoned. Versions are retained. Audit is append-only.
46
+ 6. **Deny always wins.** When rules conflict, DENY overrides ALLOW.
47
+ 7. **Revocation is immediate.** Same-transaction enforcement, not eventual consistency.
48
+ 8. **Everything is versioned.** Every mutation creates a new version.
49
+ 9. **Everything is rollbackable.** Any action can be reversed to any point in time.
50
+ 10. **Secrets never leak.** Values never appear in audit trails, snapshots, or connector traffic.
51
+
52
+ ## Development
53
+
54
+ ```bash
55
+ pip install -e ".[dev]"
56
+ python3.13 -m pytest # run full suite (1,410 tests)
57
+ python3.13 -m pytest tests/test_objects/ # run one layer
58
+ ```
59
+
60
+ Test fixtures are in `tests/conftest.py`:
61
+ - `sqlite_backend` — in-memory SQLite, initialized with schema, closed after test
62
+ - `registry` — fresh Registry instance per test
63
+ - `_reset_global_state` (autouse) — resets singletons between tests
64
+
65
+ ## Code Conventions
66
+
67
+ ### Dataclasses
68
+
69
+ All models use `@dataclass(frozen=True, slots=True)` for immutability and memory efficiency. Mutable models (like `Principal`) use `@dataclass(slots=True)` without frozen.
70
+
71
+ ### IDs and Timestamps
72
+
73
+ ```python
74
+ from scoped.types import generate_id, now_utc
75
+ id = generate_id() # UUID hex string
76
+ ts = now_utc() # datetime in UTC
77
+ ```
78
+
79
+ ### Storage Backend
80
+
81
+ All persistence goes through `StorageBackend`. Never write raw SQL outside the storage layer.
82
+
83
+ ```python
84
+ from scoped.storage.sqlite import SQLiteBackend
85
+
86
+ backend = SQLiteBackend(":memory:")
87
+ backend.initialize() # creates all tables — call once
88
+
89
+ # Queries
90
+ row = backend.fetch_one("SELECT ...", (param,))
91
+ rows = backend.fetch_all("SELECT ...", (param,))
92
+
93
+ # Writes (use transactions)
94
+ with backend.transaction() as tx:
95
+ tx.execute("INSERT ...", (param,))
96
+ tx.commit()
97
+ ```
98
+
99
+ ### Identity & Context
100
+
101
+ Every operation needs an acting principal. Use `ScopedContext` as a context manager:
102
+
103
+ ```python
104
+ from scoped.identity.context import ScopedContext
105
+ from scoped.identity.principal import PrincipalStore
106
+
107
+ principals = PrincipalStore(backend)
108
+ user = principals.create_principal(kind="user", display_name="Alice")
109
+
110
+ with ScopedContext(principal=user):
111
+ # All operations here are attributed to `user`
112
+ ctx = ScopedContext.current() # get active context
113
+ ```
114
+
115
+ ### Objects — Creator-Private by Default
116
+
117
+ ```python
118
+ from scoped.objects.manager import ScopedManager
119
+
120
+ manager = ScopedManager(backend)
121
+
122
+ # Create (creator-private)
123
+ obj, version = manager.create(object_type="document", owner_id=user.id, data={"title": "Draft"})
124
+
125
+ # Read (owner-only — returns None if not owner)
126
+ obj = manager.get(obj.id, principal_id=user.id)
127
+
128
+ # Update (creates new version)
129
+ obj, new_ver = manager.update(obj.id, principal_id=user.id, data={"title": "Final"})
130
+
131
+ # Soft delete
132
+ tombstone = manager.tombstone(obj.id, principal_id=user.id, reason="obsolete")
133
+ ```
134
+
135
+ **Important:** `ScopedManager.get()` enforces **owner-only** access. Scope projections enable visibility through separate query paths (tenancy engine), not through the manager.
136
+
137
+ ### Sharing via Scopes and Projections
138
+
139
+ ```python
140
+ from scoped.tenancy.lifecycle import ScopeLifecycle
141
+ from scoped.tenancy.projection import ProjectionManager
142
+ from scoped.tenancy.models import ScopeRole, AccessLevel
143
+
144
+ scopes = ScopeLifecycle(backend)
145
+ projections = ProjectionManager(backend)
146
+
147
+ # Create scope (owner auto-added as OWNER member)
148
+ scope = scopes.create_scope(name="Team Alpha", owner_id=user.id)
149
+
150
+ # Add members (requires granted_by and ScopeRole enum)
151
+ scopes.add_member(scope.id, principal_id=bob.id, role=ScopeRole.EDITOR, granted_by=user.id)
152
+
153
+ # Project object into scope (only owner can project)
154
+ projections.project(scope_id=scope.id, object_id=obj.id, projected_by=user.id)
155
+
156
+ # Revoke projection
157
+ projections.revoke_projection(scope_id=scope.id, object_id=obj.id, revoked_by=user.id)
158
+ ```
159
+
160
+ ### Audit Trail
161
+
162
+ ```python
163
+ from scoped.audit.writer import AuditWriter
164
+ from scoped.types import ActionType
165
+
166
+ writer = AuditWriter(backend)
167
+ entry = writer.record(
168
+ actor_id=user.id,
169
+ action=ActionType.CREATE,
170
+ target_type="document",
171
+ target_id=obj.id,
172
+ )
173
+ ```
174
+
175
+ ### Rules Engine
176
+
177
+ ```python
178
+ from scoped.rules.engine import RuleStore, RuleEngine
179
+ from scoped.rules.models import RuleType, RuleEffect, BindingTargetType
180
+
181
+ store = RuleStore(backend)
182
+ rule = store.create_rule(
183
+ name="deny-external",
184
+ rule_type=RuleType.ACCESS,
185
+ effect=RuleEffect.DENY,
186
+ priority=10,
187
+ created_by=admin.id,
188
+ )
189
+ store.bind_rule(rule.id, target_type=BindingTargetType.SCOPE, target_id=scope.id, bound_by=admin.id)
190
+
191
+ engine = RuleEngine(backend)
192
+ result = engine.evaluate(action="read", principal_id=user.id, scope_id=scope.id)
193
+ # result.allowed -> bool
194
+ ```
195
+
196
+ ### Events
197
+
198
+ ```python
199
+ from scoped.events import EventBus, EventType, SubscriptionManager
200
+
201
+ bus = EventBus(backend)
202
+ event = bus.emit(
203
+ EventType.OBJECT_CREATED,
204
+ actor_id=user.id,
205
+ target_type="document",
206
+ target_id=doc.id,
207
+ )
208
+ ```
209
+
210
+ ### Notifications
211
+
212
+ ```python
213
+ from scoped.notifications import NotificationEngine, NotificationChannel
214
+
215
+ engine = NotificationEngine(backend)
216
+ rule = engine.create_rule(
217
+ name="Deploy Alerts",
218
+ owner_id=admin.id,
219
+ event_types=["deployment_completed"],
220
+ recipient_ids=[ops.id],
221
+ channel=NotificationChannel.IN_APP,
222
+ )
223
+ notifications = engine.process_event(event)
224
+ ```
225
+
226
+ ### Scheduling
227
+
228
+ ```python
229
+ from scoped.scheduling import Scheduler, JobQueue
230
+
231
+ scheduler = Scheduler(backend)
232
+ action = scheduler.create_action(
233
+ name="Nightly cleanup",
234
+ owner_id=admin.id,
235
+ action_type="cleanup",
236
+ action_config={"max_age_hours": 24},
237
+ next_run_at=tomorrow_2am,
238
+ )
239
+
240
+ queue = JobQueue(backend, executor=my_executor)
241
+ job = queue.enqueue(name="Cleanup", action_type="cleanup", action_config={}, owner_id=admin.id)
242
+ queue.run_next()
243
+ ```
244
+
245
+ ## Common Pitfalls
246
+
247
+ - **`create_scope()` not `create()`** — `ScopeLifecycle` method is `create_scope()`
248
+ - **`create_principal()` not `create()`** — `PrincipalStore` method is `create_principal()`
249
+ - **`add_member()` requires `granted_by` and `ScopeRole` enum** — not a string role
250
+ - **`revoke_projection()` not `revoke()`** — `ProjectionManager` method name
251
+ - **FK constraints in tests** — to create orphaned data for compliance testing, wrap with `PRAGMA foreign_keys = OFF/ON`
252
+ - **`ScopedManager.get()` is owner-only** — projections don't grant manager-level access
253
+ - **Rollback traces vs DB state** — `RollbackExecutor._apply_rollback_state()` only modifies DB for `target_type == "object"` literally; `ScopedManager` uses the actual object_type (e.g., "document") as target_type
254
+ - **`backend.initialize()` required** — always call after creating `SQLiteBackend`
255
+
256
+ ## Framework Adapters (`scoped.contrib`)
257
+
258
+ All adapters are optional — install with extras: `pip install scoped[django]`, etc.
259
+
260
+ ### Django
261
+
262
+ ```python
263
+ # settings.py
264
+ INSTALLED_APPS = ["scoped.contrib.django"]
265
+ MIDDLEWARE = ["scoped.contrib.django.middleware.ScopedContextMiddleware"]
266
+ SCOPED_PRINCIPAL_HEADER = "HTTP_X_SCOPED_PRINCIPAL_ID"
267
+
268
+ # Management commands: scoped_health, scoped_audit, scoped_compliance
269
+ ```
270
+
271
+ ### FastAPI
272
+
273
+ ```python
274
+ from fastapi import FastAPI
275
+ from scoped.contrib.fastapi.middleware import ScopedContextMiddleware
276
+ from scoped.contrib.fastapi.router import router as scoped_router
277
+ from scoped.contrib.fastapi.dependencies import get_scoped_context, get_principal
278
+
279
+ app = FastAPI()
280
+ app.add_middleware(ScopedContextMiddleware, backend=backend)
281
+ app.include_router(scoped_router) # adds /scoped/health, /scoped/audit
282
+ ```
283
+
284
+ ### Flask
285
+
286
+ ```python
287
+ from flask import Flask
288
+ from scoped.contrib.flask.extension import ScopedExtension
289
+ from scoped.contrib.flask.admin import admin_bp
290
+
291
+ app = Flask(__name__)
292
+ scoped = ScopedExtension(app) # auto-inits backend, injects g.scoped_context
293
+ app.register_blueprint(admin_bp) # adds /scoped/health, /scoped/audit
294
+ ```
295
+
296
+ ### MCP (Model Context Protocol)
297
+
298
+ ```python
299
+ from scoped.contrib.mcp.server import create_scoped_server
300
+
301
+ mcp = create_scoped_server(backend) # registers tools + resources
302
+ mcp.run()
303
+ # Tools: create_principal, create_object, get_object, create_scope, list_audit, health_check
304
+ # Resources: scoped://principals, scoped://health, scoped://audit/recent
305
+ ```
306
+
307
+ ## Project Structure
308
+
309
+ ```
310
+ scoped/
311
+ __init__.py # version
312
+ conf.py # ScopedConfig
313
+ exceptions.py # all framework exceptions
314
+ types.py # generate_id, now_utc, URN, ActionType, Lifecycle
315
+
316
+ registry/ # Layer 1
317
+ identity/ # Layer 2
318
+ objects/ # Layer 3 + blobs, search, import/export
319
+ tenancy/ # Layer 4 + config hierarchy
320
+ rules/ # Layer 5 + redaction, rate limits, quotas, feature flags
321
+ audit/ # Layer 6
322
+ temporal/ # Layer 7
323
+ environments/ # Layer 8
324
+ flow/ # Layer 9
325
+ deployments/ # Layer 10
326
+ secrets/ # Layer 11
327
+ integrations/ # Layer 12
328
+ connector/ # Layer 13 + marketplace/
329
+ events/ # Layer 14
330
+ notifications/ # Layer 15
331
+ scheduling/ # Layer 16
332
+ testing/ # Layer 0 (compliance)
333
+ storage/ # backends + migrations + tiering
334
+ contrib/ # Phase D: Framework adapters
335
+ _base.py # shared utilities (build_services, resolve_principal)
336
+ django/ # D1: Django adapter
337
+ fastapi/ # D2: FastAPI adapter
338
+ flask/ # D3: Flask adapter
339
+ mcp/ # D4: MCP adapter
340
+
341
+ tests/
342
+ conftest.py # shared fixtures
343
+ test_registry/ # ... one directory per layer
344
+ test_compliance/
345
+ test_contrib/ # adapter tests (D1-D4)
346
+ test_integration/ # end-to-end tests
347
+
348
+ docs/
349
+ architecture.md # full architecture document
350
+ layers/ # per-layer documentation (00-16)
351
+ extensions/ # A1-A9 extension docs
352
+ ```
353
+
354
+ ## Documentation
355
+
356
+ - [Architecture Overview](docs/architecture.md) — the full system design
357
+ - [Layer Docs](docs/layers/) — one file per layer (00-compliance through 16-scheduling)
358
+ - [Extension Docs](docs/extensions/) — A1-migrations through A9-import-export
359
+
360
+ ## Using Scoped in Another Project
361
+
362
+ When building an application on Scoped, the typical bootstrap is:
363
+
364
+ ```python
365
+ from scoped.storage.sqlite import SQLiteBackend
366
+ from scoped.identity.principal import PrincipalStore
367
+ from scoped.objects.manager import ScopedManager
368
+ from scoped.tenancy.lifecycle import ScopeLifecycle
369
+ from scoped.tenancy.projection import ProjectionManager
370
+ from scoped.audit.writer import AuditWriter
371
+ from scoped.rules.engine import RuleStore, RuleEngine
372
+
373
+ # 1. Initialize storage
374
+ backend = SQLiteBackend("app.db")
375
+ backend.initialize()
376
+
377
+ # 2. Create stores
378
+ principals = PrincipalStore(backend)
379
+ manager = ScopedManager(backend)
380
+ scopes = ScopeLifecycle(backend)
381
+ projections = ProjectionManager(backend)
382
+ audit = AuditWriter(backend)
383
+ rules = RuleStore(backend)
384
+
385
+ # 3. Create a principal (the acting user)
386
+ user = principals.create_principal(kind="user", display_name="Alice")
387
+
388
+ # 4. Everything after this requires ScopedContext
389
+ from scoped.identity.context import ScopedContext
390
+
391
+ with ScopedContext(principal=user):
392
+ obj, ver = manager.create(object_type="task", owner_id=user.id, data={"title": "Hello"})
393
+ scope = scopes.create_scope(name="My Team", owner_id=user.id)
394
+ projections.project(scope_id=scope.id, object_id=obj.id, projected_by=user.id)
395
+ ```
pyscoped-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kwip-info
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.