@shortlink-org/portolan 0.1.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.
Files changed (826) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +387 -0
  3. package/catalog/enum_test.go +46 -0
  4. package/catalog/model.go +932 -0
  5. package/catalog/roundtrip_test.go +185 -0
  6. package/catalog/via_test.go +38 -0
  7. package/cli/portolan.mjs +368 -0
  8. package/go.mod +14 -0
  9. package/go.sum +14 -0
  10. package/index.html +13 -0
  11. package/internal/commands/cargo.go +154 -0
  12. package/internal/commands/commands.go +143 -0
  13. package/internal/commands/commands_test.go +323 -0
  14. package/internal/commands/gradle.go +77 -0
  15. package/internal/commands/justfile.go +82 -0
  16. package/internal/commands/makefile.go +106 -0
  17. package/internal/commands/maven.go +93 -0
  18. package/internal/commands/packagejson.go +159 -0
  19. package/internal/commands/pyproject.go +169 -0
  20. package/internal/commands/taskfile.go +101 -0
  21. package/internal/commands/testdata/estate/.cargo/config.toml +7 -0
  22. package/internal/commands/testdata/estate/Makefile +33 -0
  23. package/internal/commands/testdata/estate/Taskfile.yml +21 -0
  24. package/internal/commands/testdata/estate/build.gradle.kts +21 -0
  25. package/internal/commands/testdata/estate/justfile +20 -0
  26. package/internal/commands/testdata/estate/package.json +13 -0
  27. package/internal/commands/testdata/estate/pom.xml +29 -0
  28. package/internal/commands/testdata/estate/pyproject.toml +27 -0
  29. package/internal/commands/testdata/estate/xtask/src/main.rs +27 -0
  30. package/internal/commands/testdata/golden/commands.json +305 -0
  31. package/internal/gohttp/analyze.go +2500 -0
  32. package/internal/gohttp/endpoints.go +1067 -0
  33. package/internal/gohttp/roots.go +320 -0
  34. package/internal/gohttp/typed.go +143 -0
  35. package/internal/goscan/constants.go +85 -0
  36. package/internal/goscan/goscan_test.go +227 -0
  37. package/internal/goscan/names.go +52 -0
  38. package/internal/goscan/parse_test.go +11 -0
  39. package/internal/goscan/source.go +36 -0
  40. package/internal/goscan/tree.go +155 -0
  41. package/internal/goscan/types.go +99 -0
  42. package/internal/wsdl/ids.go +127 -0
  43. package/internal/wsdl/ids_test.go +21 -0
  44. package/internal/wsdl/model.go +62 -0
  45. package/internal/wsdl/parse.go +920 -0
  46. package/internal/wsdl/parse_test.go +133 -0
  47. package/package.json +117 -0
  48. package/plugin/describe.go +107 -0
  49. package/plugin/describe_test.go +114 -0
  50. package/plugin/protocol.go +117 -0
  51. package/plugin/schematest/schematest.go +126 -0
  52. package/plugins/README.md +1160 -0
  53. package/plugins/extract-adr/describe.go +19 -0
  54. package/plugins/extract-adr/describe_test.go +11 -0
  55. package/plugins/extract-adr/extract.go +153 -0
  56. package/plugins/extract-adr/extract_test.go +350 -0
  57. package/plugins/extract-adr/history.go +99 -0
  58. package/plugins/extract-adr/main.go +65 -0
  59. package/plugins/extract-adr/options.schema.json +26 -0
  60. package/plugins/extract-adr/parse.go +642 -0
  61. package/plugins/extract-adr/parse_test.go +405 -0
  62. package/plugins/extract-asyncapi/describe.go +19 -0
  63. package/plugins/extract-asyncapi/describe_test.go +11 -0
  64. package/plugins/extract-asyncapi/extract.go +315 -0
  65. package/plugins/extract-asyncapi/extract_test.go +197 -0
  66. package/plugins/extract-asyncapi/main.go +48 -0
  67. package/plugins/extract-asyncapi/options.schema.json +26 -0
  68. package/plugins/extract-asyncapi/spec.go +151 -0
  69. package/plugins/extract-celery/README.md +169 -0
  70. package/plugins/extract-celery/extract.py +346 -0
  71. package/plugins/extract-celery/extract_test.py +192 -0
  72. package/plugins/extract-celery/main.py +66 -0
  73. package/plugins/extract-celery/options.py +31 -0
  74. package/plugins/extract-celery/options.schema.json +31 -0
  75. package/plugins/extract-celery/producers.py +156 -0
  76. package/plugins/extract-celery/routes_test.py +106 -0
  77. package/plugins/extract-commands/describe.go +19 -0
  78. package/plugins/extract-commands/describe_test.go +11 -0
  79. package/plugins/extract-commands/extract.go +79 -0
  80. package/plugins/extract-commands/extract_test.go +92 -0
  81. package/plugins/extract-commands/main.go +55 -0
  82. package/plugins/extract-commands/options.schema.json +20 -0
  83. package/plugins/extract-csr/avro.go +258 -0
  84. package/plugins/extract-csr/describe.go +19 -0
  85. package/plugins/extract-csr/describe_test.go +11 -0
  86. package/plugins/extract-csr/extract.go +338 -0
  87. package/plugins/extract-csr/extract_test.go +374 -0
  88. package/plugins/extract-csr/jsonschema.go +343 -0
  89. package/plugins/extract-csr/lock.go +25 -0
  90. package/plugins/extract-csr/main.go +84 -0
  91. package/plugins/extract-csr/options.schema.json +43 -0
  92. package/plugins/extract-csr/subject.go +102 -0
  93. package/plugins/extract-django/README.md +386 -0
  94. package/plugins/extract-django/apps.py +100 -0
  95. package/plugins/extract-django/auth.py +302 -0
  96. package/plugins/extract-django/auth_test.py +188 -0
  97. package/plugins/extract-django/clients.py +121 -0
  98. package/plugins/extract-django/contracts.py +458 -0
  99. package/plugins/extract-django/database.py +119 -0
  100. package/plugins/extract-django/domain.py +318 -0
  101. package/plugins/extract-django/events.py +86 -0
  102. package/plugins/extract-django/extract.py +601 -0
  103. package/plugins/extract-django/extract_test.py +397 -0
  104. package/plugins/extract-django/flows.py +1278 -0
  105. package/plugins/extract-django/flows_test.py +338 -0
  106. package/plugins/extract-django/ids.py +42 -0
  107. package/plugins/extract-django/ids_test.py +30 -0
  108. package/plugins/extract-django/lifecycle.py +222 -0
  109. package/plugins/extract-django/lifecycle_test.py +76 -0
  110. package/plugins/extract-django/main.py +66 -0
  111. package/plugins/extract-django/openapi.py +229 -0
  112. package/plugins/extract-django/openapi_test.py +60 -0
  113. package/plugins/extract-django/operations.py +96 -0
  114. package/plugins/extract-django/options.py +61 -0
  115. package/plugins/extract-django/options.schema.json +126 -0
  116. package/plugins/extract-django/routing.py +214 -0
  117. package/plugins/extract-django/routing_test.py +198 -0
  118. package/plugins/extract-django/serializers.py +558 -0
  119. package/plugins/extract-django/store.py +434 -0
  120. package/plugins/extract-django/transport.py +242 -0
  121. package/plugins/extract-flows/describe.go +19 -0
  122. package/plugins/extract-flows/describe_test.go +11 -0
  123. package/plugins/extract-flows/extract.go +91 -0
  124. package/plugins/extract-flows/main.go +45 -0
  125. package/plugins/extract-flows/options.schema.json +16 -0
  126. package/plugins/extract-flows/parse.go +593 -0
  127. package/plugins/extract-flows/parse_test.go +204 -0
  128. package/plugins/extract-glossary/describe.go +19 -0
  129. package/plugins/extract-glossary/describe_test.go +11 -0
  130. package/plugins/extract-glossary/extract.go +115 -0
  131. package/plugins/extract-glossary/extract_test.go +220 -0
  132. package/plugins/extract-glossary/main.go +59 -0
  133. package/plugins/extract-glossary/options.schema.json +21 -0
  134. package/plugins/extract-glossary/parse.go +214 -0
  135. package/plugins/extract-glossary/parse_test.go +203 -0
  136. package/plugins/extract-go/aggregate.go +214 -0
  137. package/plugins/extract-go/client.go +409 -0
  138. package/plugins/extract-go/client_test.go +266 -0
  139. package/plugins/extract-go/describe.go +19 -0
  140. package/plugins/extract-go/describe_test.go +11 -0
  141. package/plugins/extract-go/enum.go +195 -0
  142. package/plugins/extract-go/enum_test.go +82 -0
  143. package/plugins/extract-go/event.go +99 -0
  144. package/plugins/extract-go/extract.go +191 -0
  145. package/plugins/extract-go/extract_test.go +261 -0
  146. package/plugins/extract-go/flow.go +1441 -0
  147. package/plugins/extract-go/flow_test.go +609 -0
  148. package/plugins/extract-go/httpclient.go +174 -0
  149. package/plugins/extract-go/httpclient_test.go +296 -0
  150. package/plugins/extract-go/ids.go +92 -0
  151. package/plugins/extract-go/layout.go +225 -0
  152. package/plugins/extract-go/layout_test.go +125 -0
  153. package/plugins/extract-go/lifecycle.go +324 -0
  154. package/plugins/extract-go/lifecycle_test.go +108 -0
  155. package/plugins/extract-go/main.go +79 -0
  156. package/plugins/extract-go/operation.go +157 -0
  157. package/plugins/extract-go/options.schema.json +66 -0
  158. package/plugins/extract-go/source.go +316 -0
  159. package/plugins/extract-go/transport.go +321 -0
  160. package/plugins/extract-go/transport_test.go +145 -0
  161. package/plugins/extract-go/wiring.go +434 -0
  162. package/plugins/extract-go-nats/describe.go +19 -0
  163. package/plugins/extract-go-nats/describe_test.go +11 -0
  164. package/plugins/extract-go-nats/extract.go +177 -0
  165. package/plugins/extract-go-nats/extract_test.go +389 -0
  166. package/plugins/extract-go-nats/index.go +379 -0
  167. package/plugins/extract-go-nats/main.go +42 -0
  168. package/plugins/extract-go-nats/options.schema.json +21 -0
  169. package/plugins/extract-go-nats/resolve.go +161 -0
  170. package/plugins/extract-go-nats/sites.go +224 -0
  171. package/plugins/extract-graphql/describe.go +19 -0
  172. package/plugins/extract-graphql/describe_test.go +11 -0
  173. package/plugins/extract-graphql/extract.go +433 -0
  174. package/plugins/extract-graphql/extract_test.go +256 -0
  175. package/plugins/extract-graphql/ids.go +49 -0
  176. package/plugins/extract-graphql/lex.go +237 -0
  177. package/plugins/extract-graphql/main.go +51 -0
  178. package/plugins/extract-graphql/options.schema.json +31 -0
  179. package/plugins/extract-graphql/parse.go +621 -0
  180. package/plugins/extract-graphql/parse_test.go +122 -0
  181. package/plugins/extract-http-clients/describe.go +19 -0
  182. package/plugins/extract-http-clients/describe_test.go +11 -0
  183. package/plugins/extract-http-clients/extract.go +705 -0
  184. package/plugins/extract-http-clients/extract_test.go +1263 -0
  185. package/plugins/extract-http-clients/main.go +42 -0
  186. package/plugins/extract-http-clients/options.schema.json +33 -0
  187. package/plugins/extract-java/README.md +190 -0
  188. package/plugins/extract-java/build/org/portolan/extract/Catalog.class +0 -0
  189. package/plugins/extract-java/build/org/portolan/extract/Clients$1.class +0 -0
  190. package/plugins/extract-java/build/org/portolan/extract/Clients$2.class +0 -0
  191. package/plugins/extract-java/build/org/portolan/extract/Clients$Call.class +0 -0
  192. package/plugins/extract-java/build/org/portolan/extract/Clients$Client.class +0 -0
  193. package/plugins/extract-java/build/org/portolan/extract/Clients$Route.class +0 -0
  194. package/plugins/extract-java/build/org/portolan/extract/Clients.class +0 -0
  195. package/plugins/extract-java/build/org/portolan/extract/Domain$Aggregate.class +0 -0
  196. package/plugins/extract-java/build/org/portolan/extract/Domain.class +0 -0
  197. package/plugins/extract-java/build/org/portolan/extract/Events$Found.class +0 -0
  198. package/plugins/extract-java/build/org/portolan/extract/Events.class +0 -0
  199. package/plugins/extract-java/build/org/portolan/extract/Extract.class +0 -0
  200. package/plugins/extract-java/build/org/portolan/extract/Flows$1.class +0 -0
  201. package/plugins/extract-java/build/org/portolan/extract/Flows$Binding.class +0 -0
  202. package/plugins/extract-java/build/org/portolan/extract/Flows$Draft.class +0 -0
  203. package/plugins/extract-java/build/org/portolan/extract/Flows$Frame.class +0 -0
  204. package/plugins/extract-java/build/org/portolan/extract/Flows$Options.class +0 -0
  205. package/plugins/extract-java/build/org/portolan/extract/Flows.class +0 -0
  206. package/plugins/extract-java/build/org/portolan/extract/Ids.class +0 -0
  207. package/plugins/extract-java/build/org/portolan/extract/Json$Reader.class +0 -0
  208. package/plugins/extract-java/build/org/portolan/extract/Json.class +0 -0
  209. package/plugins/extract-java/build/org/portolan/extract/Lifecycle$1.class +0 -0
  210. package/plugins/extract-java/build/org/portolan/extract/Lifecycle$Move.class +0 -0
  211. package/plugins/extract-java/build/org/portolan/extract/Lifecycle.class +0 -0
  212. package/plugins/extract-java/build/org/portolan/extract/Main.class +0 -0
  213. package/plugins/extract-java/build/org/portolan/extract/OpenApi$Operation.class +0 -0
  214. package/plugins/extract-java/build/org/portolan/extract/OpenApi$Spec.class +0 -0
  215. package/plugins/extract-java/build/org/portolan/extract/OpenApi.class +0 -0
  216. package/plugins/extract-java/build/org/portolan/extract/Operations$1.class +0 -0
  217. package/plugins/extract-java/build/org/portolan/extract/Operations$UseCase.class +0 -0
  218. package/plugins/extract-java/build/org/portolan/extract/Operations.class +0 -0
  219. package/plugins/extract-java/build/org/portolan/extract/Proto$Rpc.class +0 -0
  220. package/plugins/extract-java/build/org/portolan/extract/Proto$Service.class +0 -0
  221. package/plugins/extract-java/build/org/portolan/extract/Proto.class +0 -0
  222. package/plugins/extract-java/build/org/portolan/extract/Protocol$Builder.class +0 -0
  223. package/plugins/extract-java/build/org/portolan/extract/Protocol$Input.class +0 -0
  224. package/plugins/extract-java/build/org/portolan/extract/Protocol$Options.class +0 -0
  225. package/plugins/extract-java/build/org/portolan/extract/Protocol.class +0 -0
  226. package/plugins/extract-java/build/org/portolan/extract/Source$Project.class +0 -0
  227. package/plugins/extract-java/build/org/portolan/extract/Source$Unit.class +0 -0
  228. package/plugins/extract-java/build/org/portolan/extract/Source.class +0 -0
  229. package/plugins/extract-java/build/org/portolan/extract/Transport$Endpoint.class +0 -0
  230. package/plugins/extract-java/build/org/portolan/extract/Transport.class +0 -0
  231. package/plugins/extract-java/build/org/portolan/extract/Yaml$Line.class +0 -0
  232. package/plugins/extract-java/build/org/portolan/extract/Yaml$Reader.class +0 -0
  233. package/plugins/extract-java/build/org/portolan/extract/Yaml.class +0 -0
  234. package/plugins/extract-java/options.schema.json +70 -0
  235. package/plugins/extract-openapi/describe.go +19 -0
  236. package/plugins/extract-openapi/describe_test.go +11 -0
  237. package/plugins/extract-openapi/discover.go +243 -0
  238. package/plugins/extract-openapi/extract.go +526 -0
  239. package/plugins/extract-openapi/extract_test.go +545 -0
  240. package/plugins/extract-openapi/main.go +75 -0
  241. package/plugins/extract-openapi/options.schema.json +62 -0
  242. package/plugins/extract-openapi/spec.go +350 -0
  243. package/plugins/extract-project/README.md +22 -0
  244. package/plugins/extract-project/describe.go +19 -0
  245. package/plugins/extract-project/describe_test.go +11 -0
  246. package/plugins/extract-project/extract.go +221 -0
  247. package/plugins/extract-project/extract_test.go +109 -0
  248. package/plugins/extract-project/main.go +41 -0
  249. package/plugins/extract-project/options.schema.json +48 -0
  250. package/plugins/extract-proto/ast.go +125 -0
  251. package/plugins/extract-proto/consumes.go +77 -0
  252. package/plugins/extract-proto/describe.go +19 -0
  253. package/plugins/extract-proto/extract.go +293 -0
  254. package/plugins/extract-proto/extract_test.go +459 -0
  255. package/plugins/extract-proto/ids.go +89 -0
  256. package/plugins/extract-proto/ids_test.go +57 -0
  257. package/plugins/extract-proto/lex.go +285 -0
  258. package/plugins/extract-proto/main.go +100 -0
  259. package/plugins/extract-proto/module.go +120 -0
  260. package/plugins/extract-proto/options.schema.json +51 -0
  261. package/plugins/extract-proto/parse.go +720 -0
  262. package/plugins/extract-proto/parse_test.go +307 -0
  263. package/plugins/extract-proto/provides.go +236 -0
  264. package/plugins/extract-proto/resolve.go +222 -0
  265. package/plugins/extract-proto/resolve_test.go +119 -0
  266. package/plugins/extract-python-kafka/README.md +36 -0
  267. package/plugins/extract-python-kafka/extract.py +211 -0
  268. package/plugins/extract-python-kafka/extract_test.py +68 -0
  269. package/plugins/extract-python-kafka/main.py +59 -0
  270. package/plugins/extract-python-kafka/options.py +29 -0
  271. package/plugins/extract-python-kafka/options.schema.json +31 -0
  272. package/plugins/extract-redis/README.md +11 -0
  273. package/plugins/extract-redis/describe.go +19 -0
  274. package/plugins/extract-redis/describe_test.go +11 -0
  275. package/plugins/extract-redis/extract.go +183 -0
  276. package/plugins/extract-redis/extract_test.go +168 -0
  277. package/plugins/extract-redis/keyspaces.go +469 -0
  278. package/plugins/extract-redis/main.go +44 -0
  279. package/plugins/extract-redis/options.schema.json +30 -0
  280. package/plugins/extract-river/describe.go +19 -0
  281. package/plugins/extract-river/describe_test.go +11 -0
  282. package/plugins/extract-river/extract.go +507 -0
  283. package/plugins/extract-river/extract_test.go +132 -0
  284. package/plugins/extract-river/main.go +42 -0
  285. package/plugins/extract-river/options.schema.json +21 -0
  286. package/plugins/extract-rust/Cargo.lock +133 -0
  287. package/plugins/extract-rust/Cargo.toml +23 -0
  288. package/plugins/extract-rust/README.md +204 -0
  289. package/plugins/extract-rust/options.schema.json +65 -0
  290. package/plugins/extract-rust/rustfmt.toml +1 -0
  291. package/plugins/extract-sql/ddl.go +893 -0
  292. package/plugins/extract-sql/ddl_test.go +401 -0
  293. package/plugins/extract-sql/describe.go +19 -0
  294. package/plugins/extract-sql/describe_test.go +11 -0
  295. package/plugins/extract-sql/layout.go +221 -0
  296. package/plugins/extract-sql/layout_test.go +55 -0
  297. package/plugins/extract-sql/lineage.go +107 -0
  298. package/plugins/extract-sql/main.go +141 -0
  299. package/plugins/extract-sql/maps.go +564 -0
  300. package/plugins/extract-sql/maps_java.go +117 -0
  301. package/plugins/extract-sql/maps_rust.go +333 -0
  302. package/plugins/extract-sql/maps_rust_test.go +70 -0
  303. package/plugins/extract-sql/maps_test.go +204 -0
  304. package/plugins/extract-sql/maps_ts.go +398 -0
  305. package/plugins/extract-sql/maps_ts_test.go +136 -0
  306. package/plugins/extract-sql/options.schema.json +53 -0
  307. package/plugins/extract-sql/projection.go +70 -0
  308. package/plugins/extract-sql/projection_test.go +50 -0
  309. package/plugins/extract-sql/store.go +420 -0
  310. package/plugins/extract-sql/store_test.go +233 -0
  311. package/plugins/extract-sql/view.go +295 -0
  312. package/plugins/extract-ts/README.md +306 -0
  313. package/plugins/extract-ts/ast.test.ts +178 -0
  314. package/plugins/extract-ts/ast.ts +648 -0
  315. package/plugins/extract-ts/clients.ts +185 -0
  316. package/plugins/extract-ts/domain.ts +164 -0
  317. package/plugins/extract-ts/extract.test.ts +208 -0
  318. package/plugins/extract-ts/extract.ts +200 -0
  319. package/plugins/extract-ts/flows.ts +783 -0
  320. package/plugins/extract-ts/graphql.test.ts +73 -0
  321. package/plugins/extract-ts/graphql.ts +181 -0
  322. package/plugins/extract-ts/ids.test.ts +21 -0
  323. package/plugins/extract-ts/ids.ts +52 -0
  324. package/plugins/extract-ts/lifecycle.ts +138 -0
  325. package/plugins/extract-ts/main.ts +48 -0
  326. package/plugins/extract-ts/openapi.test.ts +64 -0
  327. package/plugins/extract-ts/openapi.ts +99 -0
  328. package/plugins/extract-ts/operations.ts +93 -0
  329. package/plugins/extract-ts/options.schema.json +96 -0
  330. package/plugins/extract-ts/source.test.ts +174 -0
  331. package/plugins/extract-ts/source.ts +465 -0
  332. package/plugins/extract-ts/transport.ts +147 -0
  333. package/plugins/extract-ts/tsconfig.json +13 -0
  334. package/plugins/extract-ts/wiring.ts +190 -0
  335. package/plugins/extract-watermill/describe.go +19 -0
  336. package/plugins/extract-watermill/describe_test.go +11 -0
  337. package/plugins/extract-watermill/extract.go +1228 -0
  338. package/plugins/extract-watermill/extract_test.go +234 -0
  339. package/plugins/extract-watermill/main.go +41 -0
  340. package/plugins/extract-watermill/options.schema.json +21 -0
  341. package/plugins/extract-wsdl/describe.go +19 -0
  342. package/plugins/extract-wsdl/describe_test.go +11 -0
  343. package/plugins/extract-wsdl/extract.go +148 -0
  344. package/plugins/extract-wsdl/extract_test.go +45 -0
  345. package/plugins/extract-wsdl/main.go +53 -0
  346. package/plugins/extract-wsdl/options.schema.json +59 -0
  347. package/plugins/fetch-bsr/auth.go +114 -0
  348. package/plugins/fetch-bsr/bsr.go +240 -0
  349. package/plugins/fetch-bsr/cache.go +66 -0
  350. package/plugins/fetch-bsr/describe.go +19 -0
  351. package/plugins/fetch-bsr/fetch.go +192 -0
  352. package/plugins/fetch-bsr/fetch_test.go +465 -0
  353. package/plugins/fetch-bsr/lock.go +71 -0
  354. package/plugins/fetch-bsr/main.go +117 -0
  355. package/plugins/fetch-bsr/options.schema.json +42 -0
  356. package/plugins/fetch-csr/auth.go +95 -0
  357. package/plugins/fetch-csr/cache.go +69 -0
  358. package/plugins/fetch-csr/describe.go +19 -0
  359. package/plugins/fetch-csr/describe_test.go +11 -0
  360. package/plugins/fetch-csr/fetch.go +254 -0
  361. package/plugins/fetch-csr/fetch_test.go +494 -0
  362. package/plugins/fetch-csr/lock.go +95 -0
  363. package/plugins/fetch-csr/main.go +122 -0
  364. package/plugins/fetch-csr/options.schema.json +42 -0
  365. package/plugins/fetch-csr/registry.go +209 -0
  366. package/plugins/fetch-git/cache.go +65 -0
  367. package/plugins/fetch-git/describe.go +19 -0
  368. package/plugins/fetch-git/describe_test.go +11 -0
  369. package/plugins/fetch-git/fetch.go +181 -0
  370. package/plugins/fetch-git/fetch_test.go +332 -0
  371. package/plugins/fetch-git/git.go +169 -0
  372. package/plugins/fetch-git/lock.go +72 -0
  373. package/plugins/fetch-git/main.go +127 -0
  374. package/plugins/fetch-git/offline.go +39 -0
  375. package/plugins/fetch-git/options.schema.json +42 -0
  376. package/plugins/fetch-git/pin.go +90 -0
  377. package/plugins/fetch-git/pin_test.go +74 -0
  378. package/plugins/gen-backstage/describe.go +17 -0
  379. package/plugins/gen-backstage/main.go +22 -0
  380. package/plugins/gen-backstage/options.schema.json +30 -0
  381. package/plugins/gen-backstage/plugin.go +473 -0
  382. package/plugins/gen-backstage/plugin_test.go +145 -0
  383. package/plugins/gen-backstage.wasm +0 -0
  384. package/plugins/gen-markdown/adr.go +162 -0
  385. package/plugins/gen-markdown/aggregate.go +362 -0
  386. package/plugins/gen-markdown/canonical.go +93 -0
  387. package/plugins/gen-markdown/context.go +90 -0
  388. package/plugins/gen-markdown/coverage_test.go +89 -0
  389. package/plugins/gen-markdown/describe.go +19 -0
  390. package/plugins/gen-markdown/describe_test.go +11 -0
  391. package/plugins/gen-markdown/external.go +71 -0
  392. package/plugins/gen-markdown/flow.go +277 -0
  393. package/plugins/gen-markdown/glossary.go +76 -0
  394. package/plugins/gen-markdown/glossary_test.go +148 -0
  395. package/plugins/gen-markdown/llms.go +302 -0
  396. package/plugins/gen-markdown/main.go +22 -0
  397. package/plugins/gen-markdown/markdown.go +254 -0
  398. package/plugins/gen-markdown/markdown_test.go +100 -0
  399. package/plugins/gen-markdown/module.go +107 -0
  400. package/plugins/gen-markdown/options.schema.json +16 -0
  401. package/plugins/gen-markdown/plugin.go +39 -0
  402. package/plugins/gen-markdown/quality_test.go +176 -0
  403. package/plugins/gen-markdown/redis_test.go +38 -0
  404. package/plugins/gen-markdown/render.go +344 -0
  405. package/plugins/gen-markdown/render_test.go +186 -0
  406. package/plugins/gen-markdown/service.go +456 -0
  407. package/plugins/gen-markdown/source.go +177 -0
  408. package/plugins/gen-markdown/store.go +201 -0
  409. package/plugins/gen-markdown.wasm +0 -0
  410. package/plugins/gen-mermaid/describe.go +17 -0
  411. package/plugins/gen-mermaid/main.go +22 -0
  412. package/plugins/gen-mermaid/options.schema.json +10 -0
  413. package/plugins/gen-mermaid/plugin.go +104 -0
  414. package/plugins/gen-mermaid/plugin_test.go +33 -0
  415. package/plugins/gen-mermaid.wasm +0 -0
  416. package/plugins/openapi/ids.go +261 -0
  417. package/plugins/openapi/ids_test.go +98 -0
  418. package/plugins/pyplugin/catalog.py +209 -0
  419. package/plugins/pyplugin/celery_conf.py +436 -0
  420. package/plugins/pyplugin/celery_tasks.py +76 -0
  421. package/plugins/pyplugin/kafka.py +570 -0
  422. package/plugins/pyplugin/names.py +38 -0
  423. package/plugins/pyplugin/protocol.py +79 -0
  424. package/plugins/pyplugin/source.py +285 -0
  425. package/plugins/verify-codeowners/describe.go +19 -0
  426. package/plugins/verify-codeowners/describe_test.go +11 -0
  427. package/plugins/verify-codeowners/main.go +75 -0
  428. package/plugins/verify-codeowners/match.go +85 -0
  429. package/plugins/verify-codeowners/match_test.go +47 -0
  430. package/plugins/verify-codeowners/options.schema.json +15 -0
  431. package/plugins/verify-codeowners/owners.go +164 -0
  432. package/plugins/verify-codeowners/owners_test.go +225 -0
  433. package/plugins/verify-codeowners/parse.go +90 -0
  434. package/plugins/verify-codeowners/parse_test.go +62 -0
  435. package/plugins/verify-otel/describe.go +19 -0
  436. package/plugins/verify-otel/describe_test.go +11 -0
  437. package/plugins/verify-otel/main.go +53 -0
  438. package/plugins/verify-otel/match.go +336 -0
  439. package/plugins/verify-otel/options.schema.json +30 -0
  440. package/plugins/verify-otel/otlp.go +200 -0
  441. package/plugins/verify-otel/verify.go +734 -0
  442. package/plugins/verify-otel/verify_test.go +460 -0
  443. package/portolan.json +1073 -0
  444. package/public/favicon.svg +12 -0
  445. package/schema/portolan.schema.json +2558 -0
  446. package/scripts/README.md +53 -0
  447. package/scripts/build-report.mjs +60 -0
  448. package/scripts/build-report.test.mjs +44 -0
  449. package/scripts/builtin-plugins.mjs +49 -0
  450. package/scripts/catalog-sources.mjs +67 -0
  451. package/scripts/diff.mjs +315 -0
  452. package/scripts/diff.test.mjs +151 -0
  453. package/scripts/forge-comment.mjs +144 -0
  454. package/scripts/forge-comment.test.mjs +151 -0
  455. package/scripts/forge-release.mjs +138 -0
  456. package/scripts/forge-release.test.mjs +106 -0
  457. package/scripts/forge.mjs +61 -0
  458. package/scripts/gen-likec4.mjs +854 -0
  459. package/scripts/gen-likec4.test.mjs +258 -0
  460. package/scripts/gen.mjs +603 -0
  461. package/scripts/generated-docs.test.mjs +66 -0
  462. package/scripts/local-api.mjs +1192 -0
  463. package/scripts/local-api.test.mjs +387 -0
  464. package/scripts/manifest.mjs +214 -0
  465. package/scripts/manifest.test.mjs +148 -0
  466. package/scripts/output-path.mjs +79 -0
  467. package/scripts/output-path.test.mjs +45 -0
  468. package/scripts/package-smoke.mjs +37 -0
  469. package/scripts/plugin-host.mjs +419 -0
  470. package/scripts/plugin-host.test.mjs +109 -0
  471. package/scripts/plugin-wasm-worker.mjs +34 -0
  472. package/scripts/run-builtin.mjs +81 -0
  473. package/scripts/schema.mjs +357 -0
  474. package/scripts/site-docs.mjs +295 -0
  475. package/scripts/site-docs.test.mjs +181 -0
  476. package/scripts/vendor-lock.mjs +58 -0
  477. package/scripts/vendor-lock.test.mjs +69 -0
  478. package/src/README.md +38 -0
  479. package/src/app/App.tsx +448 -0
  480. package/src/app/BranchPicker.test.ts +46 -0
  481. package/src/app/BranchPicker.tsx +153 -0
  482. package/src/app/Breadcrumbs.test.ts +38 -0
  483. package/src/app/Breadcrumbs.tsx +223 -0
  484. package/src/app/BuildStamp.tsx +146 -0
  485. package/src/app/CommandPalette.tsx +292 -0
  486. package/src/app/HashScroll.tsx +45 -0
  487. package/src/app/Sidebar.tsx +1742 -0
  488. package/src/app/TopBar.tsx +393 -0
  489. package/src/app/density.tsx +64 -0
  490. package/src/app/forge-access.test.ts +27 -0
  491. package/src/app/forge-access.tsx +80 -0
  492. package/src/app/panels.tsx +141 -0
  493. package/src/app/pins.tsx +242 -0
  494. package/src/app/query-client.ts +24 -0
  495. package/src/app/responsive.ts +55 -0
  496. package/src/app/shortcuts.test.ts +39 -0
  497. package/src/app/shortcuts.tsx +282 -0
  498. package/src/app/theme.tsx +51 -0
  499. package/src/app/title.test.ts +14 -0
  500. package/src/app/title.ts +30 -0
  501. package/src/app/toast.tsx +59 -0
  502. package/src/app/tree-keys.test.ts +80 -0
  503. package/src/app/tree-keys.ts +87 -0
  504. package/src/app/ui-store.ts +52 -0
  505. package/src/catalog-error.test.ts +105 -0
  506. package/src/catalog-profile.test.ts +59 -0
  507. package/src/catalog-profile.ts +101 -0
  508. package/src/catalog-stores.test.ts +431 -0
  509. package/src/catalog.test.ts +1215 -0
  510. package/src/catalog.ts +3125 -0
  511. package/src/chat/Cards.tsx +408 -0
  512. package/src/chat/ChatPanel.tsx +79 -0
  513. package/src/chat/ChatSettings.tsx +219 -0
  514. package/src/chat/Composer.tsx +99 -0
  515. package/src/chat/Conversation.tsx +281 -0
  516. package/src/chat/Header.tsx +46 -0
  517. package/src/chat/Message.tsx +49 -0
  518. package/src/chat/Notice.tsx +195 -0
  519. package/src/chat/Starter.tsx +67 -0
  520. package/src/chat/Steps.tsx +45 -0
  521. package/src/chat/Waiting.tsx +87 -0
  522. package/src/chat/flags.test.ts +59 -0
  523. package/src/chat/flags.ts +155 -0
  524. package/src/chat/linkify.test.ts +30 -0
  525. package/src/chat/linkify.ts +45 -0
  526. package/src/chat/prefs.ts +56 -0
  527. package/src/chat/prompt.test.ts +43 -0
  528. package/src/chat/prompt.ts +157 -0
  529. package/src/chat/store.ts +35 -0
  530. package/src/chat/tools.ts +58 -0
  531. package/src/chat/transport.ts +70 -0
  532. package/src/components/AdrRow.tsx +29 -0
  533. package/src/components/AnchorLink.tsx +67 -0
  534. package/src/components/ApiReference.tsx +134 -0
  535. package/src/components/AsyncApiReference.tsx +120 -0
  536. package/src/components/CatalogStamp.tsx +155 -0
  537. package/src/components/ChannelRows.tsx +132 -0
  538. package/src/components/CommandRows.tsx +139 -0
  539. package/src/components/DiagramSkeleton.tsx +71 -0
  540. package/src/components/EditorLink.tsx +85 -0
  541. package/src/components/FieldTree.tsx +305 -0
  542. package/src/components/FlowTrigger.tsx +34 -0
  543. package/src/components/Ident.tsx +89 -0
  544. package/src/components/Integrations.tsx +243 -0
  545. package/src/components/LifecycleDiagram.tsx +110 -0
  546. package/src/components/MachineDocs.tsx +42 -0
  547. package/src/components/Markdown.tsx +173 -0
  548. package/src/components/MarkdownTable.tsx +206 -0
  549. package/src/components/Mermaid.tsx +211 -0
  550. package/src/components/MethodRows.tsx +309 -0
  551. package/src/components/Overlay.tsx +125 -0
  552. package/src/components/PageHeader.tsx +189 -0
  553. package/src/components/RowActions.tsx +97 -0
  554. package/src/components/SchemaDocument.tsx +89 -0
  555. package/src/components/Select.tsx +126 -0
  556. package/src/components/ShapeRows.tsx +118 -0
  557. package/src/components/SourceDoc.tsx +82 -0
  558. package/src/components/SourcePreview.tsx +441 -0
  559. package/src/components/TabRow.tsx +182 -0
  560. package/src/components/TechIcon.tsx +34 -0
  561. package/src/components/Toc.tsx +132 -0
  562. package/src/components/WhatLinksHere.tsx +273 -0
  563. package/src/components/WsdlReference.tsx +84 -0
  564. package/src/components/ddd-icons.tsx +107 -0
  565. package/src/components/kind.tsx +157 -0
  566. package/src/components/logo.tsx +61 -0
  567. package/src/components/primitives.tsx +264 -0
  568. package/src/data.test.ts +18 -0
  569. package/src/data.ts +202 -0
  570. package/src/enrich.test.ts +1150 -0
  571. package/src/enrich.ts +672 -0
  572. package/src/er/ErCanvas.tsx +533 -0
  573. package/src/er/RedisSchema.tsx +74 -0
  574. package/src/er/RelationCard.tsx +267 -0
  575. package/src/er/StoreHeader.tsx +155 -0
  576. package/src/er/TableNode.tsx +84 -0
  577. package/src/er/ViewNode.tsx +83 -0
  578. package/src/er/layout.test.ts +115 -0
  579. package/src/er/layout.ts +77 -0
  580. package/src/er/lineage.test.ts +140 -0
  581. package/src/er/lineage.ts +107 -0
  582. package/src/er/markers.tsx +79 -0
  583. package/src/er/spec.test.ts +344 -0
  584. package/src/er/spec.ts +426 -0
  585. package/src/flow/ChainList.tsx +162 -0
  586. package/src/flow/FlowTable.tsx +123 -0
  587. package/src/flow/FlowToolbar.tsx +372 -0
  588. package/src/flow/StepDetail.tsx +380 -0
  589. package/src/flow/StepRail.tsx +428 -0
  590. package/src/flow/answers.test.ts +50 -0
  591. package/src/flow/answers.ts +58 -0
  592. package/src/flow/chain.test.ts +383 -0
  593. package/src/flow/chain.ts +353 -0
  594. package/src/flow/chapters.test.ts +185 -0
  595. package/src/flow/chapters.ts +225 -0
  596. package/src/flow/continues.test.ts +102 -0
  597. package/src/flow/continues.ts +65 -0
  598. package/src/flow/cross-context.test.ts +97 -0
  599. package/src/flow/cross-context.ts +35 -0
  600. package/src/flow/mermaid.test.ts +22 -0
  601. package/src/flow/mermaid.ts +141 -0
  602. package/src/flow/outline.test.ts +212 -0
  603. package/src/flow/outline.ts +170 -0
  604. package/src/flow/paths.test.ts +129 -0
  605. package/src/flow/paths.ts +147 -0
  606. package/src/flow/prefs.test.ts +80 -0
  607. package/src/flow/prefs.ts +104 -0
  608. package/src/graph/DependencyGraph.tsx +283 -0
  609. package/src/graph/DependencyNodes.tsx +162 -0
  610. package/src/graph/EdgeLabel.tsx +61 -0
  611. package/src/graph/FocusedEventGraph.tsx +211 -0
  612. package/src/graph/GraphToolbar.tsx +187 -0
  613. package/src/graph/RoutedEdge.tsx +80 -0
  614. package/src/graph/dependency-layout.test.ts +360 -0
  615. package/src/graph/dependency-layout.ts +444 -0
  616. package/src/graph/elk.test.ts +70 -0
  617. package/src/graph/elk.ts +287 -0
  618. package/src/graph/nodes.tsx +97 -0
  619. package/src/graph/theme.ts +81 -0
  620. package/src/graph/useElkFlow.ts +125 -0
  621. package/src/index.css +1547 -0
  622. package/src/language/InLanguage.tsx +40 -0
  623. package/src/language/TermCard.tsx +132 -0
  624. package/src/language/cards.test.ts +114 -0
  625. package/src/language/cards.ts +111 -0
  626. package/src/lib/admonition.test.ts +49 -0
  627. package/src/lib/admonition.ts +48 -0
  628. package/src/lib/adr.test.ts +131 -0
  629. package/src/lib/adr.ts +68 -0
  630. package/src/lib/api.test.ts +122 -0
  631. package/src/lib/api.ts +135 -0
  632. package/src/lib/backlinks.test.ts +330 -0
  633. package/src/lib/backlinks.ts +567 -0
  634. package/src/lib/branch-compare.ts +16 -0
  635. package/src/lib/build-info.test.ts +76 -0
  636. package/src/lib/build-info.ts +80 -0
  637. package/src/lib/catalog-diff.test.ts +275 -0
  638. package/src/lib/catalog-diff.ts +655 -0
  639. package/src/lib/clipboard.ts +43 -0
  640. package/src/lib/comparison-memory.test.ts +40 -0
  641. package/src/lib/comparison-memory.ts +39 -0
  642. package/src/lib/context-color.ts +27 -0
  643. package/src/lib/context-map.test.ts +148 -0
  644. package/src/lib/context-map.ts +399 -0
  645. package/src/lib/data-model.test.ts +245 -0
  646. package/src/lib/data-model.ts +399 -0
  647. package/src/lib/data-problems.test.ts +178 -0
  648. package/src/lib/data-problems.ts +314 -0
  649. package/src/lib/derive.test.ts +251 -0
  650. package/src/lib/derive.ts +515 -0
  651. package/src/lib/editor-link.test.ts +125 -0
  652. package/src/lib/editor-link.ts +96 -0
  653. package/src/lib/editor-prefs.ts +27 -0
  654. package/src/lib/event-graph.test.ts +237 -0
  655. package/src/lib/event-graph.ts +327 -0
  656. package/src/lib/export-canvas.ts +37 -0
  657. package/src/lib/export-file.test.ts +30 -0
  658. package/src/lib/export-file.ts +20 -0
  659. package/src/lib/flow-tree.test.ts +177 -0
  660. package/src/lib/flow-tree.ts +160 -0
  661. package/src/lib/forge-refs.test.ts +50 -0
  662. package/src/lib/forge-refs.ts +60 -0
  663. package/src/lib/format.test.ts +35 -0
  664. package/src/lib/format.ts +64 -0
  665. package/src/lib/github-catalog.test.ts +301 -0
  666. package/src/lib/github-catalog.ts +610 -0
  667. package/src/lib/integrations.test.ts +119 -0
  668. package/src/lib/integrations.ts +133 -0
  669. package/src/lib/kinds.test.ts +91 -0
  670. package/src/lib/kinds.ts +204 -0
  671. package/src/lib/lifecycle.test.ts +93 -0
  672. package/src/lib/lifecycle.ts +165 -0
  673. package/src/lib/local-api.ts +194 -0
  674. package/src/lib/motion-features.ts +11 -0
  675. package/src/lib/motion.test.ts +120 -0
  676. package/src/lib/motion.tsx +269 -0
  677. package/src/lib/palette-recent.test.ts +80 -0
  678. package/src/lib/palette-recent.ts +90 -0
  679. package/src/lib/palette.test.ts +365 -0
  680. package/src/lib/palette.ts +593 -0
  681. package/src/lib/pins.test.ts +139 -0
  682. package/src/lib/pins.ts +130 -0
  683. package/src/lib/problems.test.ts +112 -0
  684. package/src/lib/project-preview.ts +5 -0
  685. package/src/lib/proto-problems.test.ts +121 -0
  686. package/src/lib/proto-problems.ts +65 -0
  687. package/src/lib/queries.test.ts +113 -0
  688. package/src/lib/queries.ts +131 -0
  689. package/src/lib/registry.test.ts +219 -0
  690. package/src/lib/registry.ts +208 -0
  691. package/src/lib/scenarios.ts +547 -0
  692. package/src/lib/setup-info.test.ts +199 -0
  693. package/src/lib/setup-info.ts +415 -0
  694. package/src/lib/shape.test.ts +289 -0
  695. package/src/lib/shape.ts +454 -0
  696. package/src/lib/sidebar-prefs.test.ts +32 -0
  697. package/src/lib/sidebar-prefs.ts +75 -0
  698. package/src/lib/source-code.test.ts +159 -0
  699. package/src/lib/source-code.ts +286 -0
  700. package/src/lib/source-doc.test.ts +131 -0
  701. package/src/lib/source-doc.ts +103 -0
  702. package/src/lib/source-highlight.test.ts +29 -0
  703. package/src/lib/source-highlight.ts +24 -0
  704. package/src/lib/source-link.test.ts +153 -0
  705. package/src/lib/source-link.ts +201 -0
  706. package/src/lib/spec-files.test.ts +24 -0
  707. package/src/lib/spec-files.ts +23 -0
  708. package/src/lib/table-directive.test.ts +139 -0
  709. package/src/lib/table-directive.ts +106 -0
  710. package/src/lib/tech.test.ts +120 -0
  711. package/src/lib/tech.ts +421 -0
  712. package/src/lib/terms.test.ts +67 -0
  713. package/src/lib/terms.ts +179 -0
  714. package/src/lib/wire-problems.test.ts +263 -0
  715. package/src/lib/wire-problems.ts +281 -0
  716. package/src/likec4/C4View.tsx +55 -0
  717. package/src/likec4/CanvasBridge.tsx +187 -0
  718. package/src/likec4/FlowView.tsx +235 -0
  719. package/src/likec4/InteractiveView.tsx +144 -0
  720. package/src/likec4/canvas-viewport.test.ts +149 -0
  721. package/src/likec4/canvas-viewport.ts +135 -0
  722. package/src/likec4/flow-edges.test.ts +51 -0
  723. package/src/likec4/flow-edges.ts +89 -0
  724. package/src/likec4/frame-theme.test.ts +76 -0
  725. package/src/likec4/frame-theme.ts +101 -0
  726. package/src/likec4/highlight-css.test.ts +49 -0
  727. package/src/likec4/highlight-css.ts +52 -0
  728. package/src/likec4/ids.test.ts +151 -0
  729. package/src/likec4/ids.ts +115 -0
  730. package/src/likec4/levels.tsx +70 -0
  731. package/src/likec4/mapping.test.ts +66 -0
  732. package/src/likec4/mapping.ts +54 -0
  733. package/src/likec4/reserved.json +141 -0
  734. package/src/likec4/view-index.ts +78 -0
  735. package/src/main.tsx +13 -0
  736. package/src/map/ContextMapGraph.tsx +274 -0
  737. package/src/map/ContextNode.tsx +70 -0
  738. package/src/map/FloatingEdge.tsx +86 -0
  739. package/src/merge.test.ts +1038 -0
  740. package/src/merge.ts +1004 -0
  741. package/src/pages/AdrDetail.tsx +242 -0
  742. package/src/pages/AdrIndex.tsx +114 -0
  743. package/src/pages/AggregatePage.tsx +727 -0
  744. package/src/pages/BlockPage.tsx +478 -0
  745. package/src/pages/CatalogFailure.tsx +111 -0
  746. package/src/pages/Changes.tsx +313 -0
  747. package/src/pages/ContextMap.tsx +534 -0
  748. package/src/pages/ContextPage.tsx +346 -0
  749. package/src/pages/EnumPage.tsx +282 -0
  750. package/src/pages/EventPage.tsx +686 -0
  751. package/src/pages/ExternalPage.tsx +204 -0
  752. package/src/pages/FlowDetail.tsx +663 -0
  753. package/src/pages/FlowIndex.tsx +303 -0
  754. package/src/pages/GraphPage.tsx +217 -0
  755. package/src/pages/Language.tsx +257 -0
  756. package/src/pages/ModulePage.tsx +366 -0
  757. package/src/pages/NotFound.tsx +54 -0
  758. package/src/pages/Overview.tsx +344 -0
  759. package/src/pages/Problems.tsx +360 -0
  760. package/src/pages/RegistryIndex.tsx +118 -0
  761. package/src/pages/ServicePage.tsx +746 -0
  762. package/src/pages/Settings.tsx +975 -0
  763. package/src/pages/StorePage.tsx +114 -0
  764. package/src/peek/PeekCard.test.ts +35 -0
  765. package/src/peek/PeekCard.tsx +118 -0
  766. package/src/peek/PeekLayer.tsx +147 -0
  767. package/src/peek/model.test.ts +156 -0
  768. package/src/peek/model.ts +253 -0
  769. package/src/routes.test.ts +222 -0
  770. package/src/routes.ts +449 -0
  771. package/src/selection/DetailPanel.tsx +1407 -0
  772. package/src/selection/hash.test.ts +73 -0
  773. package/src/selection/hash.ts +58 -0
  774. package/src/selection/model.test.ts +199 -0
  775. package/src/selection/model.ts +473 -0
  776. package/src/selection/pages.test.ts +115 -0
  777. package/src/selection/pages.ts +268 -0
  778. package/src/selection/store.test.ts +62 -0
  779. package/src/selection/store.ts +46 -0
  780. package/src/selection/sync.tsx +99 -0
  781. package/src/table/ColumnsMenu.tsx +72 -0
  782. package/src/table/DataTable.tsx +780 -0
  783. package/src/table/Facets.tsx +54 -0
  784. package/src/table/GroupMenu.tsx +69 -0
  785. package/src/table/Toolbar.tsx +190 -0
  786. package/src/table/cells.tsx +117 -0
  787. package/src/table/compare.test.ts +117 -0
  788. package/src/table/compare.ts +196 -0
  789. package/src/table/export.test.ts +88 -0
  790. package/src/table/export.ts +66 -0
  791. package/src/table/facet-groups.test.ts +74 -0
  792. package/src/table/facet-groups.ts +56 -0
  793. package/src/table/grouping.test.ts +84 -0
  794. package/src/table/grouping.ts +82 -0
  795. package/src/table/infer.test.ts +57 -0
  796. package/src/table/infer.ts +50 -0
  797. package/src/table/persist.test.ts +76 -0
  798. package/src/table/persist.ts +112 -0
  799. package/src/table/sort-url.test.ts +75 -0
  800. package/src/table/sort-url.ts +52 -0
  801. package/src/table/types.ts +80 -0
  802. package/src/table/useTableState.ts +220 -0
  803. package/src/test-catalog.ts +7 -0
  804. package/src/testing/estate/data__catalog.json +2847 -0
  805. package/src/testing/estate/data__flows.json +1724 -0
  806. package/src/testing/estate/examples__auth__portolan__api.json +212 -0
  807. package/src/testing/estate/examples__auth__portolan__domain.json +1204 -0
  808. package/src/testing/estate/examples__auth__portolan__glossary.json +226 -0
  809. package/src/testing/estate/examples__auth__portolan__observed.json +757 -0
  810. package/src/testing/estate/examples__auth__portolan__stores.json +195 -0
  811. package/src/testing/estate/examples__shop__cart__portolan__api.json +234 -0
  812. package/src/testing/estate/examples__shop__cart__portolan__commands.json +86 -0
  813. package/src/testing/estate/examples__shop__cart__portolan__domain.json +966 -0
  814. package/src/testing/estate/examples__shop__cart__portolan__observed.json +498 -0
  815. package/src/testing/estate/examples__shop__cart__portolan__stores.json +208 -0
  816. package/src/testing/estate/examples__shop__oms__portolan__glossary.json +98 -0
  817. package/src/testing/estate/examples__shop__oms__portolan__proto.json +186 -0
  818. package/src/testing/estate.ts +49 -0
  819. package/src/trail/Trail.tsx +81 -0
  820. package/src/trail/model.test.ts +157 -0
  821. package/src/trail/model.ts +189 -0
  822. package/src/trail/record.tsx +32 -0
  823. package/src/trail/store.test.ts +66 -0
  824. package/src/trail/store.ts +102 -0
  825. package/tsconfig.json +35 -0
  826. package/vite.config.ts +171 -0
@@ -0,0 +1,1204 @@
1
+ {
2
+ "generatedAt": "2026-09-05T01:13:04+07:00",
3
+ "commit": "80e6873",
4
+ "contexts": [
5
+ {
6
+ "id": "auth",
7
+ "slug": "auth",
8
+ "name": "Authentication",
9
+ "summary": "Who someone is, and whether they are still logged in. The only service in the estate that stores credentials, and the only one allowed to mint or revoke a session.",
10
+ "classification": "core",
11
+ "services": [
12
+ {
13
+ "id": "auth.auth",
14
+ "slug": "auth",
15
+ "name": "Authentication \u0026 Sessions",
16
+ "repo": "github.com/shortlink-org/portolan",
17
+ "path": "examples/auth",
18
+ "readme": "# Authentication \u0026 Sessions\n\nService `auth` — bounded context **auth**.\n\nOwns *who someone is* and *whether they are still logged in*. It is the only\nservice in the estate that stores credentials, and the only one allowed to mint\nor revoke a session.\n\n## What it does\n\n- Registers a user: an email address and a password, hashed before it is stored.\n- Authenticates: checks a password and answers with a user id or a refusal.\n- Replaces a password, given the current one, and ends the sessions the old one\n was issued against.\n- Starts a session on a successful login, once a risk service has allowed it,\n and hands back an opaque token.\n- Ends a session on logout.\n- Validates a token for everyone else — the hot path every authenticated\n request in `shop` goes through.\n- Locks an account after five wrong passwords in a row, for fifteen minutes,\n and says so with an event.\n\n## What it does not do\n\nNo profile data, no addresses, no payment instruments, no roles or scopes.\nOther contexts hold their own view of a customer and reference it by opaque\nuser id; nothing outside `auth` ever sees a credential.\n\nNo MFA, no email verification, no refresh tokens, no way for support to lift a\nlock early. Each of those is a real requirement somewhere, and none of them is\nhere: this service is deliberately the smallest thing that is still\nauthentication.\n\n## Decisions\n\n- [auth.0001](docs/adr/0001-events-returned-not-buffered.md) — Aggregates return their events; they do not buffer them\n- [auth.0002](docs/adr/0002-session-is-its-own-aggregate.md) — Session is its own aggregate, linked to User by id\n- [auth.0003](docs/adr/0003-expiry-publishes-nothing.md) — Session expiry publishes no event\n- [auth.0004](docs/adr/0004-lockout-is-its-own-aggregate.md) — Lockout is its own aggregate, keyed by user id\n- [auth.0005](docs/adr/0005-rules-are-specifications-at-construction.md) — Validation lives in constructors, as specifications, and applies when a value is made\n- [auth.0006](docs/adr/0006-a-password-change-ends-sessions-through-a-policy.md) — A password change ends sessions through a policy, and the domains never import each other\n- [auth.0007](docs/adr/0007-login-asks-risk-and-a-block-is-a-compromise.md) — Login asks a risk service, and a blocked attempt is treated as a compromise\n- [auth.0008](docs/adr/0008-a-cache-in-front-of-bytoken-only.md) — A cache in front of the token lookup, and nothing else\n- [auth.0009](docs/adr/0009-a-lock-answers-like-a-wrong-password.md) — A locked account answers exactly like a wrong password\n\n## Running it\n\n```bash\ndocker compose up -d\nSTORE_TYPE=postgres \\\nSTORE_POSTGRES_URI=postgres://auth:auth@localhost:5432/auth?sslmode=disable \\\n go run ./cmd/auth\n```\n\n`CACHE_TYPE=redis` with `STORE_REDIS_URI` turns the cache on; `RISK_ADDR`\npoints login at a risk service; `TRACER_URI` switches tracing on. Unset, each\nis a stand-in that keeps nothing, allows everything, or costs nothing. The\nschema is brought up to date at startup. `go test ./...` runs everything;\nwithout Docker the packages that need Postgres or redis are skipped.\n`go generate ./...` regenerates the server from the spec and the wire graph.",
19
+ "provides": [],
20
+ "consumes": [
21
+ {
22
+ "id": "risk.v1.RiskService/Assess",
23
+ "peer": "risk.v1",
24
+ "status": "unresolved",
25
+ "source": "examples/auth/internal/infrastructure/risk/gen/riskpb/risk_grpc.pb.go"
26
+ }
27
+ ],
28
+ "aggregates": [
29
+ {
30
+ "id": "auth.auth.lockout",
31
+ "slug": "lockout",
32
+ "name": "Lockout",
33
+ "readme": "# Lockout\n\nHow many wrong passwords in a row an account has taken, and whether it is\nrefusing logins because of them. One per user, identified by the user id,\nexisting from the first wrong password on. A separate aggregate from `User`:\na failed attempt is written on every wrong password and the user does not\nchange when one arrives, so the two do not share a lock.\n\n## States\n\n- **Open** — counting. `Failures` is the number of wrong passwords in a row;\n the account accepts a password. The only state a password is checked in.\n- **Locked** — until `LockedUntil`. The account refuses a password without\n checking it, with the same answer a wrong one gets. Not terminal: it ends\n by time.\n- A lock that has run out is **Open** again. Derived from time when the next\n attempt arrives; no command, no event, nothing runs. The next wrong\n password starts the count at one.\n\nThe state is read off `LockedUntil` with `now`; there is no stored flag to\ndrift from it. The moves are one table, `Rules` in `rules.go`, run through\n`go-sdk/fsm` by `trigger`: `lock` on the failure that reaches the threshold,\n`lapse` on the first attempt after a lock has run out, which is when the code\nnotices it. The run-out itself is not a move; nothing runs when it happens.\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Open : first wrong password (no event)\n Open --\u003e Open : Fail, count \u003c Threshold (no event)\n Open --\u003e Locked : Fail, count = Threshold / AccountLocked\n Open --\u003e Open : Succeed, count := 0 (no event)\n Locked --\u003e Locked : Fail, not counted (no event)\n Locked --\u003e Open : now ≥ LockedUntil (no event)\n```\n\n## Commands\n\n| Command | From | To | Event |\n|---|---|---|---|\n| `New` | — | Open, zero failures | none; nothing has happened yet |\n| `Fail` | Open, count \u003c Threshold − 1 | Open, count + 1 | none |\n| `Fail` | Open, count = Threshold − 1 | Locked | `AccountLocked` |\n| `Fail` | Locked | unchanged | none; reports \"locked nothing\" |\n| `Succeed` | Open | Open, count 0 | none; reports whether anything changed |\n| `Succeed` | Locked | unchanged | none; the lock stands |\n\n`Allows(now)` and `Locked(now)` are the read, for the caller that asks\nbefore checking a password.\n\nOne event for the whole aggregate. A wrong password that locked nothing is a\ncount, not a fact anybody consumes; a count going back to zero is\nbookkeeping; the lock running out is time passing. `AccountLocked` carries\n`Until`, so a consumer who wants to know when the account is usable again\ndoes not have to be told twice.",
34
+ "root": "Lockout",
35
+ "entities": [
36
+ {
37
+ "id": "auth.auth.lockout.lockout",
38
+ "slug": "lockout",
39
+ "name": "Lockout",
40
+ "doc": "Lockout is the aggregate root. Its identity is the user id: there is one per account, and it exists from the first wrong password on.",
41
+ "fields": [
42
+ {
43
+ "name": "UserID",
44
+ "type": "string",
45
+ "doc": ""
46
+ },
47
+ {
48
+ "name": "Failures",
49
+ "type": "int",
50
+ "doc": "Failures is the number of wrong passwords in a row. It is reset by a right one and by the count starting again after a lock has run out."
51
+ },
52
+ {
53
+ "name": "LockedUntil",
54
+ "type": "time.Time",
55
+ "doc": "LockedUntil is when the lock ends; zero while the account has never been locked. A time in the past is a lock that ran out: the state is read off it with `now`, and nothing runs when it passes."
56
+ },
57
+ {
58
+ "name": "Version",
59
+ "type": "int64",
60
+ "doc": "Version is what the store compares against before writing; see the note on user.User.Version. Zero means the lockout has never been stored."
61
+ }
62
+ ]
63
+ }
64
+ ],
65
+ "valueObjects": [],
66
+ "operations": [
67
+ {
68
+ "id": "Check",
69
+ "kind": "query",
70
+ "doc": "Answers whether an account accepts a password right now."
71
+ },
72
+ {
73
+ "id": "RecordFailure",
74
+ "kind": "command",
75
+ "doc": "Counts a wrong password against an account, and locks the account when the count reaches the threshold."
76
+ },
77
+ {
78
+ "id": "RecordSuccess",
79
+ "kind": "command",
80
+ "doc": "Clears the count of wrong passwords after a right one."
81
+ }
82
+ ],
83
+ "events": [
84
+ {
85
+ "id": "auth.auth.lockout.AccountLocked",
86
+ "slug": "account-locked",
87
+ "name": "AccountLocked",
88
+ "versions": [
89
+ {
90
+ "version": "v1",
91
+ "doc": "AccountLocked is published when an account starts refusing logins because of too many wrong passwords in a row. Until says when it stops.",
92
+ "source": "examples/auth/internal/domain/lockout/event/account_locked.go",
93
+ "fields": [
94
+ {
95
+ "name": "userID",
96
+ "type": "string",
97
+ "doc": ""
98
+ },
99
+ {
100
+ "name": "until",
101
+ "type": "time.Time",
102
+ "doc": ""
103
+ },
104
+ {
105
+ "name": "occurredAt",
106
+ "type": "time.Time",
107
+ "doc": ""
108
+ }
109
+ ]
110
+ }
111
+ ],
112
+ "consumers": [],
113
+ "wire": {
114
+ "name": "auth.AccountLocked",
115
+ "channel": "auth_lockout"
116
+ }
117
+ }
118
+ ],
119
+ "lifecycle": {
120
+ "states": [
121
+ "open",
122
+ "locked"
123
+ ],
124
+ "transitions": [
125
+ {
126
+ "from": "open",
127
+ "to": "locked",
128
+ "on": "Fail",
129
+ "emits": "auth.auth.lockout.AccountLocked",
130
+ "source": "examples/auth/internal/domain/lockout/lockout.go:95"
131
+ },
132
+ {
133
+ "from": "locked",
134
+ "to": "open",
135
+ "on": "Fail",
136
+ "source": "examples/auth/internal/domain/lockout/lockout.go:88"
137
+ },
138
+ {
139
+ "from": "locked",
140
+ "to": "open",
141
+ "on": "Succeed",
142
+ "source": "examples/auth/internal/domain/lockout/lockout.go:121"
143
+ }
144
+ ]
145
+ }
146
+ },
147
+ {
148
+ "id": "auth.auth.session",
149
+ "slug": "session",
150
+ "name": "Session",
151
+ "readme": "# Session\n\nProof that a user logged in, how long that proof is good for, and whether it\nhas been taken away. A separate aggregate from `User`: it is written far more\noften and revoked without the user changing, so the two do not share a lock.\nThey are linked by user id and nothing else.\n\n## States\n\n- **Live** — issued, not revoked, not past expiry. The only state a token is\n accepted in.\n- **Revoked** — ended by a command, with a reason. Terminal: a revoked session\n never comes back, logging in again produces a new one.\n- **Expired** — past `ExpiresAt`. Derived from time when the token is\n presented; no command, no event, nothing runs. Every consumer already knows\n the expiry from `SessionStarted`.\n\nThe state is not stored as a field. It is read off `RevokedAt` and\n`ExpiresAt` with `now`, so there is no second copy to drift. The moves are\none table, `Rules` in `rules.go`, run through `go-sdk/fsm` by `trigger`; a\ncommand that would move the session somewhere the table does not allow is\nrefused there, which is what makes `Revoke` idempotent. Expiry is not in the\ntable: it is not a move, nothing runs when it happens.\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Live : Start / SessionStarted\n Live --\u003e Revoked : Revoke(reason) / SessionEnded\n Live --\u003e Expired : now ≥ ExpiresAt (no event)\n Revoked --\u003e [*]\n Expired --\u003e [*]\n```\n\n## Commands\n\n| Command | From | To | Event |\n|---|---|---|---|\n| `Start` | — | Live | `SessionStarted` |\n| `Revoke(reason)` | Live | Revoked | `SessionEnded` |\n| `Revoke(reason)` | Revoked, Expired | unchanged | none; reports \"nothing to do\" |\n\n`Validate(now)` is the read: it says which state forbids use (`ErrRevoked`,\n`ErrExpired`) or nothing. `Live(now)` is the same question as a boolean.\n\nRevoking twice is the \"nothing to do\" answer, not a refusal: the caller asked\nfor something already true. Ending it again would publish a `SessionEnded`\nfor an ending that did not happen.",
152
+ "root": "Session",
153
+ "entities": [
154
+ {
155
+ "id": "auth.auth.session.session",
156
+ "slug": "session",
157
+ "name": "Session",
158
+ "doc": "Session is the aggregate root. Its identity is ID; the Token is a secret it carries, not what it is called.",
159
+ "fields": [
160
+ {
161
+ "name": "ID",
162
+ "type": "string",
163
+ "doc": ""
164
+ },
165
+ {
166
+ "name": "UserID",
167
+ "type": "string",
168
+ "doc": ""
169
+ },
170
+ {
171
+ "name": "Token",
172
+ "type": "token.Token",
173
+ "doc": ""
174
+ },
175
+ {
176
+ "name": "IssuedAt",
177
+ "type": "time.Time",
178
+ "doc": ""
179
+ },
180
+ {
181
+ "name": "ExpiresAt",
182
+ "type": "time.Time",
183
+ "doc": ""
184
+ },
185
+ {
186
+ "name": "RevokedAt",
187
+ "type": "time.Time",
188
+ "doc": "zero while live"
189
+ },
190
+ {
191
+ "name": "Version",
192
+ "type": "int64",
193
+ "doc": "Version is what the store compares against before writing; see the note on user.User.Version. Zero means the session has never been stored."
194
+ }
195
+ ]
196
+ }
197
+ ],
198
+ "valueObjects": [
199
+ {
200
+ "id": "auth.auth.session.token",
201
+ "slug": "token",
202
+ "name": "Token",
203
+ "doc": "Token is the opaque string a client presents instead of a password.",
204
+ "fields": [
205
+ {
206
+ "name": "value",
207
+ "type": "string",
208
+ "doc": ""
209
+ }
210
+ ]
211
+ }
212
+ ],
213
+ "operations": [
214
+ {
215
+ "id": "EndAfterCredentialChange",
216
+ "kind": "command",
217
+ "doc": "Ends the sessions a credential change invalidates."
218
+ },
219
+ {
220
+ "id": "Login",
221
+ "kind": "command",
222
+ "doc": "Turns credentials into a session.",
223
+ "exposedBy": [
224
+ "login"
225
+ ]
226
+ },
227
+ {
228
+ "id": "Logout",
229
+ "kind": "command",
230
+ "doc": "Ends the session behind a token.",
231
+ "exposedBy": [
232
+ "logout"
233
+ ]
234
+ },
235
+ {
236
+ "id": "Validate",
237
+ "kind": "query",
238
+ "doc": "Resolves a token to a live session: who is calling, and how long the answer stays good.",
239
+ "exposedBy": [
240
+ "changePassword",
241
+ "validateSession"
242
+ ]
243
+ }
244
+ ],
245
+ "events": [
246
+ {
247
+ "id": "auth.auth.session.SessionEnded",
248
+ "slug": "session-ended",
249
+ "name": "SessionEnded",
250
+ "versions": [
251
+ {
252
+ "version": "v1",
253
+ "doc": "SessionEnded is published when a session is deliberately ended.",
254
+ "source": "examples/auth/internal/domain/session/event/session_ended.go",
255
+ "fields": [
256
+ {
257
+ "name": "sessionID",
258
+ "type": "string",
259
+ "doc": ""
260
+ },
261
+ {
262
+ "name": "userID",
263
+ "type": "string",
264
+ "doc": ""
265
+ },
266
+ {
267
+ "name": "reason",
268
+ "type": "Reason",
269
+ "doc": ""
270
+ },
271
+ {
272
+ "name": "occurredAt",
273
+ "type": "time.Time",
274
+ "doc": ""
275
+ }
276
+ ]
277
+ }
278
+ ],
279
+ "consumers": [],
280
+ "wire": {
281
+ "name": "auth.SessionEnded",
282
+ "channel": "auth_session"
283
+ }
284
+ },
285
+ {
286
+ "id": "auth.auth.session.SessionStarted",
287
+ "slug": "session-started",
288
+ "name": "SessionStarted",
289
+ "versions": [
290
+ {
291
+ "version": "v1",
292
+ "doc": "SessionStarted is published on a successful login. ExpiresAt is on the event so a consumer can reason about the session's lifetime without asking auth again on every check.",
293
+ "source": "examples/auth/internal/domain/session/event/session_started.go",
294
+ "fields": [
295
+ {
296
+ "name": "sessionID",
297
+ "type": "string",
298
+ "doc": ""
299
+ },
300
+ {
301
+ "name": "userID",
302
+ "type": "string",
303
+ "doc": ""
304
+ },
305
+ {
306
+ "name": "expiresAt",
307
+ "type": "time.Time",
308
+ "doc": ""
309
+ },
310
+ {
311
+ "name": "occurredAt",
312
+ "type": "time.Time",
313
+ "doc": ""
314
+ }
315
+ ]
316
+ }
317
+ ],
318
+ "consumers": [],
319
+ "wire": {
320
+ "name": "auth.SessionStarted",
321
+ "channel": "auth_session"
322
+ }
323
+ }
324
+ ],
325
+ "lifecycle": {
326
+ "states": [
327
+ "live",
328
+ "revoked"
329
+ ],
330
+ "transitions": [
331
+ {
332
+ "from": "live",
333
+ "to": "revoked",
334
+ "on": "Revoke",
335
+ "emits": "auth.auth.session.SessionEnded",
336
+ "source": "examples/auth/internal/domain/session/session.go:88"
337
+ }
338
+ ]
339
+ }
340
+ },
341
+ {
342
+ "id": "auth.auth.user",
343
+ "slug": "user",
344
+ "name": "User",
345
+ "readme": "# User\n\nA person, the address they log in with, and the hash of the password they log\nin by. Identity is the id, minted at registration; the address can change.\n\n## States\n\nOne state. A user that exists is registered, and nothing here ends that:\nthere is no deletion, no suspension, no lockout. Each of those is a real\nrequirement somewhere and none of them is here.\n\n`ChangePassword` changes a value, not a state. It is a command with a guard\n(the current password) and an event, and the user is the same user afterwards.\n\n```mermaid\nstateDiagram-v2\n [*] --\u003e Registered : Register / UserRegistered\n Registered --\u003e Registered : ChangePassword(current, next) / PasswordChanged\n```\n\n## Commands\n\n| Command | Guard | Event |\n|---|---|---|\n| `Register` | address and password pass their policies | `UserRegistered` |\n| `ChangePassword` | the current password matches; the new one passes the policy | `PasswordChanged` |\n| `Authenticate` | — | none; a read that answers one refusal for every failure |\n\nNo command here touches a session. That a password change ends sessions is a\nrule about sessions, applied by the policy in `internal/application/policy`.",
346
+ "root": "User",
347
+ "entities": [
348
+ {
349
+ "id": "auth.auth.user.user",
350
+ "slug": "user",
351
+ "name": "User",
352
+ "doc": "User is the aggregate root. Identity is ID, minted once at registration and never reused - not the email, because people change addresses.",
353
+ "fields": [
354
+ {
355
+ "name": "ID",
356
+ "type": "string",
357
+ "doc": ""
358
+ },
359
+ {
360
+ "name": "Email",
361
+ "type": "email.Address",
362
+ "doc": ""
363
+ },
364
+ {
365
+ "name": "Password",
366
+ "type": "password.Hash",
367
+ "doc": ""
368
+ },
369
+ {
370
+ "name": "CreatedAt",
371
+ "type": "time.Time",
372
+ "doc": ""
373
+ },
374
+ {
375
+ "name": "Version",
376
+ "type": "int64",
377
+ "doc": "Version is what the store compares against before writing. It is carried on the aggregate rather than known only to the repository so that a copy which has gone stale can say so - without it, two changes made from two reads both succeed and the first one silently disappears."
378
+ }
379
+ ]
380
+ }
381
+ ],
382
+ "valueObjects": [
383
+ {
384
+ "id": "auth.auth.user.email-address",
385
+ "slug": "email-address",
386
+ "name": "email.Address",
387
+ "doc": "Address is a normalised email address.",
388
+ "fields": [
389
+ {
390
+ "name": "value",
391
+ "type": "string",
392
+ "doc": ""
393
+ }
394
+ ]
395
+ },
396
+ {
397
+ "id": "auth.auth.user.password-hash",
398
+ "slug": "password-hash",
399
+ "name": "password.Hash",
400
+ "doc": "Hash is what the user domain stores in place of a password. The plaintext never lives on an aggregate and never leaves the function that hashed it.",
401
+ "fields": [
402
+ {
403
+ "name": "algorithm",
404
+ "type": "string",
405
+ "doc": ""
406
+ },
407
+ {
408
+ "name": "iterations",
409
+ "type": "int",
410
+ "doc": ""
411
+ },
412
+ {
413
+ "name": "salt",
414
+ "type": "[]byte",
415
+ "doc": ""
416
+ },
417
+ {
418
+ "name": "digest",
419
+ "type": "[]byte",
420
+ "doc": ""
421
+ }
422
+ ]
423
+ }
424
+ ],
425
+ "operations": [
426
+ {
427
+ "id": "Authenticate",
428
+ "kind": "query",
429
+ "doc": "Checks an address and a password, and says which user they belong to."
430
+ },
431
+ {
432
+ "id": "ChangePassword",
433
+ "kind": "command",
434
+ "doc": "Replaces the password of a user, given the current one.",
435
+ "exposedBy": [
436
+ "changePassword"
437
+ ]
438
+ },
439
+ {
440
+ "id": "Get",
441
+ "kind": "query",
442
+ "doc": "Reads a user by id.",
443
+ "exposedBy": [
444
+ "getUser"
445
+ ]
446
+ },
447
+ {
448
+ "id": "Register",
449
+ "kind": "command",
450
+ "doc": "Creates a user from an email address and a password.",
451
+ "exposedBy": [
452
+ "registerUser"
453
+ ]
454
+ }
455
+ ],
456
+ "events": [
457
+ {
458
+ "id": "auth.auth.user.PasswordChanged",
459
+ "slug": "password-changed",
460
+ "name": "PasswordChanged",
461
+ "versions": [
462
+ {
463
+ "version": "v1",
464
+ "doc": "PasswordChanged is published when a user's password is replaced. It says the password is different now; it does not carry the password, old or new, in any form.",
465
+ "source": "examples/auth/internal/domain/user/event/password_changed.go",
466
+ "fields": [
467
+ {
468
+ "name": "userID",
469
+ "type": "string",
470
+ "doc": ""
471
+ },
472
+ {
473
+ "name": "by",
474
+ "type": "string",
475
+ "doc": ""
476
+ },
477
+ {
478
+ "name": "occurredAt",
479
+ "type": "time.Time",
480
+ "doc": ""
481
+ }
482
+ ]
483
+ }
484
+ ],
485
+ "consumers": [],
486
+ "wire": {
487
+ "name": "auth.PasswordChanged",
488
+ "channel": "auth_user"
489
+ }
490
+ },
491
+ {
492
+ "id": "auth.auth.user.UserRegistered",
493
+ "slug": "user-registered",
494
+ "name": "UserRegistered",
495
+ "versions": [
496
+ {
497
+ "version": "v1",
498
+ "doc": "UserRegistered is published once per user, at registration. It carries the address because consumers routinely need to reach the person, and asking auth for it on every event would make the bus useless.",
499
+ "source": "examples/auth/internal/domain/user/event/user_registered.go",
500
+ "fields": [
501
+ {
502
+ "name": "userID",
503
+ "type": "string",
504
+ "doc": ""
505
+ },
506
+ {
507
+ "name": "email",
508
+ "type": "string",
509
+ "doc": ""
510
+ },
511
+ {
512
+ "name": "occurredAt",
513
+ "type": "time.Time",
514
+ "doc": ""
515
+ }
516
+ ]
517
+ }
518
+ ],
519
+ "consumers": [],
520
+ "wire": {
521
+ "name": "auth.UserRegistered",
522
+ "channel": "auth_user"
523
+ }
524
+ }
525
+ ]
526
+ }
527
+ ]
528
+ }
529
+ ]
530
+ }
531
+ ],
532
+ "defs": {},
533
+ "flows": [
534
+ {
535
+ "id": "flow.auth-change-password",
536
+ "slug": "auth-change-password",
537
+ "name": "Change password",
538
+ "summary": "Replaces the password of a user, given the current one.",
539
+ "source": "examples/auth/internal/infrastructure/transport/http/user/change_password.go",
540
+ "owner": "auth",
541
+ "participants": [
542
+ {
543
+ "id": "client",
544
+ "kind": "actor",
545
+ "context": null
546
+ },
547
+ {
548
+ "id": "auth.auth",
549
+ "kind": "service",
550
+ "context": "auth"
551
+ },
552
+ {
553
+ "id": "auth-pg",
554
+ "kind": "store",
555
+ "context": "auth"
556
+ },
557
+ {
558
+ "id": "bus",
559
+ "kind": "broker",
560
+ "context": null
561
+ }
562
+ ],
563
+ "steps": [
564
+ {
565
+ "type": "step",
566
+ "id": "s1",
567
+ "from": "client",
568
+ "to": "auth.auth",
569
+ "kind": "rpc",
570
+ "label": "changePassword",
571
+ "status": "declared",
572
+ "line": "examples/auth/internal/infrastructure/transport/http/user/change_password.go:20"
573
+ },
574
+ {
575
+ "type": "step",
576
+ "id": "s2",
577
+ "from": "auth.auth",
578
+ "to": "auth-pg",
579
+ "kind": "call",
580
+ "label": "ByToken",
581
+ "status": "declared",
582
+ "line": "examples/auth/internal/application/session/usecases/validate/usecase.go:34"
583
+ },
584
+ {
585
+ "type": "step",
586
+ "id": "s3",
587
+ "from": "auth.auth",
588
+ "to": "auth-pg",
589
+ "kind": "call",
590
+ "label": "ByID",
591
+ "status": "declared",
592
+ "line": "examples/auth/internal/application/user/usecases/change_password/usecase.go:31"
593
+ },
594
+ {
595
+ "type": "step",
596
+ "id": "s4",
597
+ "from": "auth.auth",
598
+ "to": "auth-pg",
599
+ "kind": "call",
600
+ "label": "Save",
601
+ "status": "declared",
602
+ "line": "examples/auth/internal/application/user/usecases/change_password/usecase.go:40"
603
+ },
604
+ {
605
+ "type": "step",
606
+ "id": "s5",
607
+ "from": "auth.auth",
608
+ "to": "bus",
609
+ "kind": "event",
610
+ "ref": "auth.auth.user.PasswordChanged",
611
+ "label": "PasswordChanged",
612
+ "status": "declared",
613
+ "line": "examples/auth/internal/application/user/usecases/change_password/usecase.go:40"
614
+ }
615
+ ]
616
+ },
617
+ {
618
+ "id": "flow.auth-get-user",
619
+ "slug": "auth-get-user",
620
+ "name": "Get user",
621
+ "summary": "Reads a user by id.",
622
+ "source": "examples/auth/internal/infrastructure/transport/http/user/get.go",
623
+ "owner": "auth",
624
+ "participants": [
625
+ {
626
+ "id": "client",
627
+ "kind": "actor",
628
+ "context": null
629
+ },
630
+ {
631
+ "id": "auth.auth",
632
+ "kind": "service",
633
+ "context": "auth"
634
+ },
635
+ {
636
+ "id": "auth-pg",
637
+ "kind": "store",
638
+ "context": "auth"
639
+ }
640
+ ],
641
+ "steps": [
642
+ {
643
+ "type": "step",
644
+ "id": "s1",
645
+ "from": "client",
646
+ "to": "auth.auth",
647
+ "kind": "rpc",
648
+ "label": "getUser",
649
+ "status": "declared",
650
+ "line": "examples/auth/internal/infrastructure/transport/http/user/get.go:11"
651
+ },
652
+ {
653
+ "type": "step",
654
+ "id": "s2",
655
+ "from": "auth.auth",
656
+ "to": "auth-pg",
657
+ "kind": "call",
658
+ "label": "ByID",
659
+ "status": "declared",
660
+ "line": "examples/auth/internal/application/user/usecases/get/usecase.go:23"
661
+ }
662
+ ]
663
+ },
664
+ {
665
+ "id": "flow.auth-login",
666
+ "slug": "auth-login",
667
+ "name": "Login",
668
+ "summary": "Turns credentials into a session.",
669
+ "source": "examples/auth/internal/infrastructure/transport/http/session/login.go",
670
+ "owner": "auth",
671
+ "participants": [
672
+ {
673
+ "id": "client",
674
+ "kind": "actor",
675
+ "context": null
676
+ },
677
+ {
678
+ "id": "auth.auth",
679
+ "kind": "service",
680
+ "context": "auth"
681
+ },
682
+ {
683
+ "id": "auth-pg",
684
+ "kind": "store",
685
+ "context": "auth"
686
+ },
687
+ {
688
+ "id": "risk-v1",
689
+ "kind": "unknown",
690
+ "context": null,
691
+ "label": "risk.v1"
692
+ },
693
+ {
694
+ "id": "bus",
695
+ "kind": "broker",
696
+ "context": null
697
+ }
698
+ ],
699
+ "steps": [
700
+ {
701
+ "type": "step",
702
+ "id": "s1",
703
+ "from": "client",
704
+ "to": "auth.auth",
705
+ "kind": "rpc",
706
+ "label": "login",
707
+ "status": "declared",
708
+ "line": "examples/auth/internal/infrastructure/transport/http/session/login.go:11"
709
+ },
710
+ {
711
+ "type": "step",
712
+ "id": "s2",
713
+ "from": "auth.auth",
714
+ "to": "auth.auth",
715
+ "kind": "call",
716
+ "label": "Authenticate",
717
+ "status": "declared",
718
+ "note": "Port `Authenticator`, bound at assembly to the Authenticate use case.",
719
+ "line": "examples/auth/internal/application/session/usecases/login/usecase.go:58"
720
+ },
721
+ {
722
+ "type": "step",
723
+ "id": "s3",
724
+ "from": "auth.auth",
725
+ "to": "auth-pg",
726
+ "kind": "call",
727
+ "label": "ByEmail",
728
+ "status": "declared",
729
+ "line": "examples/auth/internal/application/user/usecases/authenticate/usecase.go:41"
730
+ },
731
+ {
732
+ "type": "step",
733
+ "id": "s4",
734
+ "from": "auth.auth",
735
+ "to": "auth.auth",
736
+ "kind": "call",
737
+ "label": "Check",
738
+ "status": "declared",
739
+ "note": "Port `Lockout`, bound at assembly to the Check use case.",
740
+ "line": "examples/auth/internal/application/user/usecases/authenticate/usecase.go:49"
741
+ },
742
+ {
743
+ "type": "step",
744
+ "id": "s5",
745
+ "from": "auth.auth",
746
+ "to": "auth-pg",
747
+ "kind": "call",
748
+ "label": "ByUserID",
749
+ "status": "declared",
750
+ "line": "examples/auth/internal/application/lockout/usecases/check/usecase.go:27"
751
+ },
752
+ {
753
+ "type": "alt",
754
+ "id": "alt9",
755
+ "branches": [
756
+ {
757
+ "title": "err != nil",
758
+ "steps": [
759
+ {
760
+ "type": "step",
761
+ "id": "s6",
762
+ "from": "auth.auth",
763
+ "to": "auth.auth",
764
+ "kind": "call",
765
+ "label": "RecordFailure",
766
+ "status": "declared",
767
+ "note": "Port `Lockout`, bound at assembly to the RecordFailure use case.",
768
+ "line": "examples/auth/internal/application/user/usecases/authenticate/usecase.go:58"
769
+ },
770
+ {
771
+ "type": "step",
772
+ "id": "s7",
773
+ "from": "auth.auth",
774
+ "to": "auth-pg",
775
+ "kind": "call",
776
+ "label": "ByUserID",
777
+ "status": "declared",
778
+ "note": "inside a loop over `retries`.",
779
+ "line": "examples/auth/internal/application/lockout/usecases/record_failure/usecase.go:37"
780
+ },
781
+ {
782
+ "type": "step",
783
+ "id": "s8",
784
+ "from": "auth.auth",
785
+ "to": "auth-pg",
786
+ "kind": "call",
787
+ "label": "Save",
788
+ "status": "declared",
789
+ "note": "inside a loop over `retries`.",
790
+ "line": "examples/auth/internal/application/lockout/usecases/record_failure/usecase.go:54"
791
+ }
792
+ ],
793
+ "terminal": true
794
+ },
795
+ {
796
+ "title": "otherwise",
797
+ "steps": []
798
+ }
799
+ ]
800
+ },
801
+ {
802
+ "type": "step",
803
+ "id": "s10",
804
+ "from": "auth.auth",
805
+ "to": "auth.auth",
806
+ "kind": "call",
807
+ "label": "RecordSuccess",
808
+ "status": "declared",
809
+ "note": "Port `Lockout`, bound at assembly to the RecordSuccess use case.",
810
+ "line": "examples/auth/internal/application/user/usecases/authenticate/usecase.go:67"
811
+ },
812
+ {
813
+ "type": "step",
814
+ "id": "s11",
815
+ "from": "auth.auth",
816
+ "to": "auth-pg",
817
+ "kind": "call",
818
+ "label": "ByUserID",
819
+ "status": "declared",
820
+ "note": "inside a loop over `retries`.",
821
+ "line": "examples/auth/internal/application/lockout/usecases/record_success/usecase.go:32"
822
+ },
823
+ {
824
+ "type": "step",
825
+ "id": "s12",
826
+ "from": "auth.auth",
827
+ "to": "auth-pg",
828
+ "kind": "call",
829
+ "label": "Save",
830
+ "status": "declared",
831
+ "note": "inside a loop over `retries`.",
832
+ "line": "examples/auth/internal/application/lockout/usecases/record_success/usecase.go:44"
833
+ },
834
+ {
835
+ "type": "step",
836
+ "id": "s13",
837
+ "from": "auth.auth",
838
+ "to": "risk-v1",
839
+ "kind": "rpc",
840
+ "ref": "risk.v1.RiskService/Assess",
841
+ "label": "Assess",
842
+ "status": "unresolved",
843
+ "line": "examples/auth/internal/application/session/usecases/login/usecase.go:63"
844
+ },
845
+ {
846
+ "type": "alt",
847
+ "id": "alt17",
848
+ "branches": [
849
+ {
850
+ "title": "verdict == VerdictBlock",
851
+ "steps": [
852
+ {
853
+ "type": "step",
854
+ "id": "s14",
855
+ "from": "auth.auth",
856
+ "to": "auth-pg",
857
+ "kind": "call",
858
+ "label": "ByUserID",
859
+ "status": "declared",
860
+ "line": "examples/auth/internal/application/session/usecases/login/usecase.go:92"
861
+ },
862
+ {
863
+ "type": "step",
864
+ "id": "s15",
865
+ "from": "auth.auth",
866
+ "to": "auth-pg",
867
+ "kind": "call",
868
+ "label": "Save",
869
+ "status": "declared",
870
+ "note": "inside a loop over `sessions`.",
871
+ "line": "examples/auth/internal/application/session/usecases/login/usecase.go:102"
872
+ },
873
+ {
874
+ "type": "step",
875
+ "id": "s16",
876
+ "from": "auth.auth",
877
+ "to": "bus",
878
+ "kind": "event",
879
+ "ref": "auth.auth.session.SessionEnded",
880
+ "label": "SessionEnded",
881
+ "status": "declared",
882
+ "note": "inside a loop over `sessions`.",
883
+ "line": "examples/auth/internal/application/session/usecases/login/usecase.go:102"
884
+ }
885
+ ],
886
+ "terminal": true
887
+ },
888
+ {
889
+ "title": "otherwise",
890
+ "steps": []
891
+ }
892
+ ]
893
+ },
894
+ {
895
+ "type": "step",
896
+ "id": "s18",
897
+ "from": "auth.auth",
898
+ "to": "auth-pg",
899
+ "kind": "call",
900
+ "label": "Save",
901
+ "status": "declared",
902
+ "line": "examples/auth/internal/application/session/usecases/login/usecase.go:78"
903
+ },
904
+ {
905
+ "type": "step",
906
+ "id": "s19",
907
+ "from": "auth.auth",
908
+ "to": "bus",
909
+ "kind": "event",
910
+ "ref": "auth.auth.session.SessionStarted",
911
+ "label": "SessionStarted",
912
+ "status": "declared",
913
+ "line": "examples/auth/internal/application/session/usecases/login/usecase.go:78"
914
+ }
915
+ ]
916
+ },
917
+ {
918
+ "id": "flow.auth-logout",
919
+ "slug": "auth-logout",
920
+ "name": "Logout",
921
+ "summary": "Ends the session behind a token.",
922
+ "source": "examples/auth/internal/infrastructure/transport/http/session/logout.go",
923
+ "owner": "auth",
924
+ "participants": [
925
+ {
926
+ "id": "client",
927
+ "kind": "actor",
928
+ "context": null
929
+ },
930
+ {
931
+ "id": "auth.auth",
932
+ "kind": "service",
933
+ "context": "auth"
934
+ },
935
+ {
936
+ "id": "auth-pg",
937
+ "kind": "store",
938
+ "context": "auth"
939
+ },
940
+ {
941
+ "id": "bus",
942
+ "kind": "broker",
943
+ "context": null
944
+ }
945
+ ],
946
+ "steps": [
947
+ {
948
+ "type": "step",
949
+ "id": "s1",
950
+ "from": "client",
951
+ "to": "auth.auth",
952
+ "kind": "rpc",
953
+ "label": "logout",
954
+ "status": "declared",
955
+ "line": "examples/auth/internal/infrastructure/transport/http/session/logout.go:15"
956
+ },
957
+ {
958
+ "type": "step",
959
+ "id": "s2",
960
+ "from": "auth.auth",
961
+ "to": "auth-pg",
962
+ "kind": "call",
963
+ "label": "ByToken",
964
+ "status": "declared",
965
+ "line": "examples/auth/internal/application/session/usecases/logout/usecase.go:35"
966
+ },
967
+ {
968
+ "type": "step",
969
+ "id": "s3",
970
+ "from": "auth.auth",
971
+ "to": "auth-pg",
972
+ "kind": "call",
973
+ "label": "Save",
974
+ "status": "declared",
975
+ "line": "examples/auth/internal/application/session/usecases/logout/usecase.go:49"
976
+ },
977
+ {
978
+ "type": "step",
979
+ "id": "s4",
980
+ "from": "auth.auth",
981
+ "to": "bus",
982
+ "kind": "event",
983
+ "ref": "auth.auth.session.SessionEnded",
984
+ "label": "SessionEnded",
985
+ "status": "declared",
986
+ "line": "examples/auth/internal/application/session/usecases/logout/usecase.go:49"
987
+ }
988
+ ]
989
+ },
990
+ {
991
+ "id": "flow.auth-register-user",
992
+ "slug": "auth-register-user",
993
+ "name": "Register user",
994
+ "summary": "Creates a user from an email address and a password.",
995
+ "source": "examples/auth/internal/infrastructure/transport/http/user/register.go",
996
+ "owner": "auth",
997
+ "participants": [
998
+ {
999
+ "id": "client",
1000
+ "kind": "actor",
1001
+ "context": null
1002
+ },
1003
+ {
1004
+ "id": "auth.auth",
1005
+ "kind": "service",
1006
+ "context": "auth"
1007
+ },
1008
+ {
1009
+ "id": "auth-pg",
1010
+ "kind": "store",
1011
+ "context": "auth"
1012
+ },
1013
+ {
1014
+ "id": "bus",
1015
+ "kind": "broker",
1016
+ "context": null
1017
+ }
1018
+ ],
1019
+ "steps": [
1020
+ {
1021
+ "type": "step",
1022
+ "id": "s1",
1023
+ "from": "client",
1024
+ "to": "auth.auth",
1025
+ "kind": "rpc",
1026
+ "label": "registerUser",
1027
+ "status": "declared",
1028
+ "line": "examples/auth/internal/infrastructure/transport/http/user/register.go:16"
1029
+ },
1030
+ {
1031
+ "type": "step",
1032
+ "id": "s2",
1033
+ "from": "auth.auth",
1034
+ "to": "auth-pg",
1035
+ "kind": "call",
1036
+ "label": "ByEmail",
1037
+ "status": "declared",
1038
+ "line": "examples/auth/internal/application/user/usecases/register/usecase.go:36"
1039
+ },
1040
+ {
1041
+ "type": "step",
1042
+ "id": "s3",
1043
+ "from": "auth.auth",
1044
+ "to": "auth-pg",
1045
+ "kind": "call",
1046
+ "label": "Save",
1047
+ "status": "declared",
1048
+ "line": "examples/auth/internal/application/user/usecases/register/usecase.go:49"
1049
+ },
1050
+ {
1051
+ "type": "step",
1052
+ "id": "s4",
1053
+ "from": "auth.auth",
1054
+ "to": "bus",
1055
+ "kind": "event",
1056
+ "ref": "auth.auth.user.UserRegistered",
1057
+ "label": "UserRegistered",
1058
+ "status": "declared",
1059
+ "line": "examples/auth/internal/application/user/usecases/register/usecase.go:49"
1060
+ }
1061
+ ]
1062
+ },
1063
+ {
1064
+ "id": "flow.auth-validate-session",
1065
+ "slug": "auth-validate-session",
1066
+ "name": "Validate session",
1067
+ "summary": "Resolves a token to a live session: who is calling, and how long the answer stays good.",
1068
+ "source": "examples/auth/internal/infrastructure/transport/http/session/validate.go",
1069
+ "owner": "auth",
1070
+ "participants": [
1071
+ {
1072
+ "id": "client",
1073
+ "kind": "actor",
1074
+ "context": null
1075
+ },
1076
+ {
1077
+ "id": "auth.auth",
1078
+ "kind": "service",
1079
+ "context": "auth"
1080
+ },
1081
+ {
1082
+ "id": "auth-pg",
1083
+ "kind": "store",
1084
+ "context": "auth"
1085
+ }
1086
+ ],
1087
+ "steps": [
1088
+ {
1089
+ "type": "step",
1090
+ "id": "s1",
1091
+ "from": "client",
1092
+ "to": "auth.auth",
1093
+ "kind": "rpc",
1094
+ "label": "validateSession",
1095
+ "status": "declared",
1096
+ "line": "examples/auth/internal/infrastructure/transport/http/session/validate.go:12"
1097
+ },
1098
+ {
1099
+ "type": "step",
1100
+ "id": "s2",
1101
+ "from": "auth.auth",
1102
+ "to": "auth-pg",
1103
+ "kind": "call",
1104
+ "label": "ByToken",
1105
+ "status": "declared",
1106
+ "line": "examples/auth/internal/application/session/usecases/validate/usecase.go:34"
1107
+ }
1108
+ ]
1109
+ },
1110
+ {
1111
+ "id": "flow.auth-revoke-sessions-on-password-change",
1112
+ "slug": "auth-revoke-sessions-on-password-change",
1113
+ "name": "Revoke sessions on password change",
1114
+ "summary": "Ends the sessions issued against a password that has just been replaced.",
1115
+ "source": "examples/auth/internal/application/policy/revoke_sessions_on_password_change.go",
1116
+ "owner": "auth",
1117
+ "participants": [
1118
+ {
1119
+ "id": "bus",
1120
+ "kind": "broker",
1121
+ "context": null
1122
+ },
1123
+ {
1124
+ "id": "auth.auth",
1125
+ "kind": "service",
1126
+ "context": "auth"
1127
+ },
1128
+ {
1129
+ "id": "auth-pg",
1130
+ "kind": "store",
1131
+ "context": "auth"
1132
+ }
1133
+ ],
1134
+ "steps": [
1135
+ {
1136
+ "type": "step",
1137
+ "id": "s1",
1138
+ "from": "bus",
1139
+ "to": "auth.auth",
1140
+ "kind": "event",
1141
+ "ref": "auth.auth.user.PasswordChanged",
1142
+ "label": "PasswordChanged",
1143
+ "status": "declared",
1144
+ "line": "examples/auth/internal/application/policy/revoke_sessions_on_password_change.go:41"
1145
+ },
1146
+ {
1147
+ "type": "step",
1148
+ "id": "s2",
1149
+ "from": "auth.auth",
1150
+ "to": "auth.auth",
1151
+ "kind": "call",
1152
+ "label": "EndAfterCredentialChange",
1153
+ "status": "declared",
1154
+ "line": "examples/auth/internal/application/policy/revoke_sessions_on_password_change.go:47"
1155
+ },
1156
+ {
1157
+ "type": "step",
1158
+ "id": "s3",
1159
+ "from": "auth.auth",
1160
+ "to": "auth-pg",
1161
+ "kind": "call",
1162
+ "label": "ByUserID",
1163
+ "status": "declared",
1164
+ "line": "examples/auth/internal/application/session/usecases/end_after_credential_change/usecase.go:40"
1165
+ },
1166
+ {
1167
+ "type": "step",
1168
+ "id": "s4",
1169
+ "from": "auth.auth",
1170
+ "to": "auth-pg",
1171
+ "kind": "call",
1172
+ "label": "ByID",
1173
+ "status": "declared",
1174
+ "note": "inside a loop over `change.Ends(sessions, uc.now())`, inside a loop over `retries`.",
1175
+ "line": "examples/auth/internal/application/session/usecases/end_after_credential_change/usecase.go:62"
1176
+ },
1177
+ {
1178
+ "type": "step",
1179
+ "id": "s5",
1180
+ "from": "auth.auth",
1181
+ "to": "auth-pg",
1182
+ "kind": "call",
1183
+ "label": "Save",
1184
+ "status": "declared",
1185
+ "note": "inside a loop over `change.Ends(sessions, uc.now())`, inside a loop over `retries`.",
1186
+ "line": "examples/auth/internal/application/session/usecases/end_after_credential_change/usecase.go:77"
1187
+ },
1188
+ {
1189
+ "type": "step",
1190
+ "id": "s6",
1191
+ "from": "auth.auth",
1192
+ "to": "bus",
1193
+ "kind": "event",
1194
+ "ref": "auth.auth.session.SessionEnded",
1195
+ "label": "SessionEnded",
1196
+ "status": "declared",
1197
+ "note": "inside a loop over `change.Ends(sessions, uc.now())`, inside a loop over `retries`.",
1198
+ "line": "examples/auth/internal/application/session/usecases/end_after_credential_change/usecase.go:77"
1199
+ }
1200
+ ]
1201
+ }
1202
+ ],
1203
+ "adrs": []
1204
+ }