seams 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 (414) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +335 -0
  3. data/LICENSE +21 -0
  4. data/README.md +104 -0
  5. data/lib/generators/seams/accounts/accounts_generator.rb +272 -0
  6. data/lib/generators/seams/accounts/templates/README.md.tt +219 -0
  7. data/lib/generators/seams/accounts/templates/app/models/account.rb.tt +124 -0
  8. data/lib/generators/seams/accounts/templates/app/models/application_record.rb.tt +7 -0
  9. data/lib/generators/seams/accounts/templates/app/models/current.rb.tt +38 -0
  10. data/lib/generators/seams/accounts/templates/app/models/membership.rb.tt +114 -0
  11. data/lib/generators/seams/accounts/templates/config/routes.rb.tt +8 -0
  12. data/lib/generators/seams/accounts/templates/db/migrate/create_accounts.rb.tt +29 -0
  13. data/lib/generators/seams/accounts/templates/db/migrate/create_accounts_memberships.rb.tt +49 -0
  14. data/lib/generators/seams/accounts/templates/lib/accounts.rb.tt +21 -0
  15. data/lib/generators/seams/accounts/templates/lib/concerns/account_scoped.rb.tt +97 -0
  16. data/lib/generators/seams/accounts/templates/lib/concerns/authorization.rb.tt +105 -0
  17. data/lib/generators/seams/accounts/templates/lib/configuration.rb.tt +26 -0
  18. data/lib/generators/seams/accounts/templates/lib/engine.rb.tt +55 -0
  19. data/lib/generators/seams/accounts/templates/spec/factories/accounts.rb.tt +49 -0
  20. data/lib/generators/seams/accounts/templates/spec/models/accounts/account_spec.rb.tt +64 -0
  21. data/lib/generators/seams/accounts/templates/spec/models/accounts/membership_spec.rb.tt +99 -0
  22. data/lib/generators/seams/accounts/templates/spec/runtime/accounts_boot_spec.rb.tt +181 -0
  23. data/lib/generators/seams/admin/admin_generator.rb +852 -0
  24. data/lib/generators/seams/admin/templates/README.md.tt +266 -0
  25. data/lib/generators/seams/admin/templates/app/controllers/admin/accounts_controller.rb.tt +16 -0
  26. data/lib/generators/seams/admin/templates/app/controllers/admin/accounts_memberships_controller.rb.tt +16 -0
  27. data/lib/generators/seams/admin/templates/app/controllers/admin/application_controller.rb.tt +282 -0
  28. data/lib/generators/seams/admin/templates/app/controllers/admin/identities_controller.rb.tt +26 -0
  29. data/lib/generators/seams/admin/templates/app/controllers/admin/invitations_controller.rb.tt +14 -0
  30. data/lib/generators/seams/admin/templates/app/controllers/admin/invoices_controller.rb.tt +14 -0
  31. data/lib/generators/seams/admin/templates/app/controllers/admin/lifetime_passes_controller.rb.tt +14 -0
  32. data/lib/generators/seams/admin/templates/app/controllers/admin/notification_preferences_controller.rb.tt +15 -0
  33. data/lib/generators/seams/admin/templates/app/controllers/admin/notifications_controller.rb.tt +18 -0
  34. data/lib/generators/seams/admin/templates/app/controllers/admin/plans_controller.rb.tt +14 -0
  35. data/lib/generators/seams/admin/templates/app/controllers/admin/subscriptions_controller.rb.tt +14 -0
  36. data/lib/generators/seams/admin/templates/app/controllers/admin/teams_controller.rb.tt +14 -0
  37. data/lib/generators/seams/admin/templates/app/controllers/admin/teams_memberships_controller.rb.tt +16 -0
  38. data/lib/generators/seams/admin/templates/app/dashboards/admin/account_dashboard.rb.tt +50 -0
  39. data/lib/generators/seams/admin/templates/app/dashboards/admin/accounts_membership_dashboard.rb.tt +58 -0
  40. data/lib/generators/seams/admin/templates/app/dashboards/admin/identity_dashboard.rb.tt +48 -0
  41. data/lib/generators/seams/admin/templates/app/dashboards/admin/invitation_dashboard.rb.tt +51 -0
  42. data/lib/generators/seams/admin/templates/app/dashboards/admin/invoice_dashboard.rb.tt +67 -0
  43. data/lib/generators/seams/admin/templates/app/dashboards/admin/lifetime_pass_dashboard.rb.tt +65 -0
  44. data/lib/generators/seams/admin/templates/app/dashboards/admin/notification_dashboard.rb.tt +58 -0
  45. data/lib/generators/seams/admin/templates/app/dashboards/admin/notification_preference_dashboard.rb.tt +43 -0
  46. data/lib/generators/seams/admin/templates/app/dashboards/admin/plan_dashboard.rb.tt +72 -0
  47. data/lib/generators/seams/admin/templates/app/dashboards/admin/subscription_dashboard.rb.tt +59 -0
  48. data/lib/generators/seams/admin/templates/app/dashboards/admin/team_dashboard.rb.tt +39 -0
  49. data/lib/generators/seams/admin/templates/app/dashboards/admin/teams_membership_dashboard.rb.tt +43 -0
  50. data/lib/generators/seams/admin/templates/app/policies/admin/platform/account_policy.rb.tt +10 -0
  51. data/lib/generators/seams/admin/templates/app/policies/admin/platform/accounts_membership_policy.rb.tt +10 -0
  52. data/lib/generators/seams/admin/templates/app/policies/admin/platform/application_policy.rb.tt +85 -0
  53. data/lib/generators/seams/admin/templates/app/policies/admin/platform/identity_policy.rb.tt +18 -0
  54. data/lib/generators/seams/admin/templates/app/policies/admin/platform/invitation_policy.rb.tt +9 -0
  55. data/lib/generators/seams/admin/templates/app/policies/admin/platform/invoice_policy.rb.tt +9 -0
  56. data/lib/generators/seams/admin/templates/app/policies/admin/platform/lifetime_pass_policy.rb.tt +9 -0
  57. data/lib/generators/seams/admin/templates/app/policies/admin/platform/notification_policy.rb.tt +9 -0
  58. data/lib/generators/seams/admin/templates/app/policies/admin/platform/notification_preference_policy.rb.tt +9 -0
  59. data/lib/generators/seams/admin/templates/app/policies/admin/platform/plan_policy.rb.tt +11 -0
  60. data/lib/generators/seams/admin/templates/app/policies/admin/platform/subscription_policy.rb.tt +9 -0
  61. data/lib/generators/seams/admin/templates/app/policies/admin/platform/team_policy.rb.tt +9 -0
  62. data/lib/generators/seams/admin/templates/app/policies/admin/platform/teams_membership_policy.rb.tt +9 -0
  63. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/account_policy.rb.tt +33 -0
  64. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/accounts_membership_policy.rb.tt +24 -0
  65. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/application_policy.rb.tt +169 -0
  66. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/identity_policy.rb.tt +67 -0
  67. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/invitation_policy.rb.tt +24 -0
  68. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/invoice_policy.rb.tt +21 -0
  69. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/lifetime_pass_policy.rb.tt +21 -0
  70. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/notification_policy.rb.tt +25 -0
  71. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/notification_preference_policy.rb.tt +23 -0
  72. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/plan_policy.rb.tt +47 -0
  73. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/subscription_policy.rb.tt +22 -0
  74. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/team_policy.rb.tt +28 -0
  75. data/lib/generators/seams/admin/templates/app/policies/admin/tenant/teams_membership_policy.rb.tt +24 -0
  76. data/lib/generators/seams/admin/templates/config/routes.rb.tt +38 -0
  77. data/lib/generators/seams/admin/templates/lib/admin.rb.tt +36 -0
  78. data/lib/generators/seams/admin/templates/lib/concerns/authenticator.rb.tt +66 -0
  79. data/lib/generators/seams/admin/templates/lib/configuration.rb.tt +90 -0
  80. data/lib/generators/seams/admin/templates/lib/context.rb.tt +44 -0
  81. data/lib/generators/seams/admin/templates/lib/engine.rb.tt +68 -0
  82. data/lib/generators/seams/admin/templates/spec/factories/admin.rb.tt +10 -0
  83. data/lib/generators/seams/admin/templates/spec/runtime/admin_boot_spec.rb.tt +604 -0
  84. data/lib/generators/seams/auth/add_oauth_provider/add_oauth_provider_generator.rb +157 -0
  85. data/lib/generators/seams/auth/add_oauth_provider/templates/adapter.rb.tt +95 -0
  86. data/lib/generators/seams/auth/add_oauth_provider/templates/adapter_spec.rb.tt +58 -0
  87. data/lib/generators/seams/auth/auth_generator.rb +311 -0
  88. data/lib/generators/seams/auth/templates/README.md.tt +289 -0
  89. data/lib/generators/seams/auth/templates/app/controllers/oauth/callbacks_controller.rb.tt +80 -0
  90. data/lib/generators/seams/auth/templates/app/controllers/password_resets_controller.rb.tt +44 -0
  91. data/lib/generators/seams/auth/templates/app/controllers/registrations_controller.rb.tt +34 -0
  92. data/lib/generators/seams/auth/templates/app/controllers/sessions_controller.rb.tt +49 -0
  93. data/lib/generators/seams/auth/templates/app/jobs/application_job.rb.tt +7 -0
  94. data/lib/generators/seams/auth/templates/app/jobs/cleanup_expired_sessions_job.rb.tt +30 -0
  95. data/lib/generators/seams/auth/templates/app/mailers/passwords_mailer.rb.tt +15 -0
  96. data/lib/generators/seams/auth/templates/app/models/api_token.rb.tt +62 -0
  97. data/lib/generators/seams/auth/templates/app/models/application_record.rb.tt +7 -0
  98. data/lib/generators/seams/auth/templates/app/models/current.rb.tt +15 -0
  99. data/lib/generators/seams/auth/templates/app/models/identity.rb.tt +74 -0
  100. data/lib/generators/seams/auth/templates/app/models/oauth/provider.rb.tt +48 -0
  101. data/lib/generators/seams/auth/templates/app/models/session.rb.tt +28 -0
  102. data/lib/generators/seams/auth/templates/app/services/authenticate_identity.rb.tt +31 -0
  103. data/lib/generators/seams/auth/templates/app/services/generate_api_token.rb.tt +35 -0
  104. data/lib/generators/seams/auth/templates/app/services/oauth/authenticator.rb.tt +94 -0
  105. data/lib/generators/seams/auth/templates/app/services/register_identity.rb.tt +57 -0
  106. data/lib/generators/seams/auth/templates/app/services/reset_password.rb.tt +41 -0
  107. data/lib/generators/seams/auth/templates/app/services/revoke_api_token.rb.tt +38 -0
  108. data/lib/generators/seams/auth/templates/app/views/password_resets/edit.html.erb.tt +12 -0
  109. data/lib/generators/seams/auth/templates/app/views/password_resets/new.html.erb.tt +11 -0
  110. data/lib/generators/seams/auth/templates/app/views/passwords_mailer/reset_email.html.erb.tt +7 -0
  111. data/lib/generators/seams/auth/templates/app/views/registrations/new.html.erb.tt +26 -0
  112. data/lib/generators/seams/auth/templates/app/views/sessions/_oauth_buttons.html.erb.tt +18 -0
  113. data/lib/generators/seams/auth/templates/app/views/sessions/new.html.erb.tt +17 -0
  114. data/lib/generators/seams/auth/templates/config/routes.rb.tt +21 -0
  115. data/lib/generators/seams/auth/templates/db/migrate/create_auth_api_tokens.rb.tt +26 -0
  116. data/lib/generators/seams/auth/templates/db/migrate/create_auth_identities.rb.tt +29 -0
  117. data/lib/generators/seams/auth/templates/db/migrate/create_auth_oauth_providers.rb.tt +35 -0
  118. data/lib/generators/seams/auth/templates/db/migrate/create_auth_sessions.rb.tt +19 -0
  119. data/lib/generators/seams/auth/templates/lib/auth.rb.tt +39 -0
  120. data/lib/generators/seams/auth/templates/lib/concerns/api_authenticatable.rb.tt +58 -0
  121. data/lib/generators/seams/auth/templates/lib/concerns/authenticatable.rb.tt +32 -0
  122. data/lib/generators/seams/auth/templates/lib/concerns/authentication.rb.tt +60 -0
  123. data/lib/generators/seams/auth/templates/lib/configuration.rb.tt +45 -0
  124. data/lib/generators/seams/auth/templates/lib/engine.rb.tt +46 -0
  125. data/lib/generators/seams/auth/templates/lib/oauth/abstract.rb.tt +87 -0
  126. data/lib/generators/seams/auth/templates/lib/oauth/github.rb.tt +112 -0
  127. data/lib/generators/seams/auth/templates/lib/oauth/google.rb.tt +78 -0
  128. data/lib/generators/seams/auth/templates/lib/tasks/auth_pii.rake.tt +68 -0
  129. data/lib/generators/seams/auth/templates/spec/factories/auth.rb.tt +38 -0
  130. data/lib/generators/seams/auth/templates/spec/mailers/passwords_mailer_spec.rb.tt +37 -0
  131. data/lib/generators/seams/auth/templates/spec/models/api_token_spec.rb.tt +84 -0
  132. data/lib/generators/seams/auth/templates/spec/models/identity_spec.rb.tt +56 -0
  133. data/lib/generators/seams/auth/templates/spec/models/oauth/provider_spec.rb.tt +64 -0
  134. data/lib/generators/seams/auth/templates/spec/models/session_spec.rb.tt +34 -0
  135. data/lib/generators/seams/auth/templates/spec/runtime/boot_spec.rb.tt +30 -0
  136. data/lib/generators/seams/auth/templates/spec/runtime/event_payload_spec.rb.tt +29 -0
  137. data/lib/generators/seams/auth/templates/spec/runtime/login_flow_spec.rb.tt +45 -0
  138. data/lib/generators/seams/billing/billing_generator.rb +476 -0
  139. data/lib/generators/seams/billing/templates/README.md.tt +355 -0
  140. data/lib/generators/seams/billing/templates/app/controllers/admin/lifetime_passes_controller.rb.tt +84 -0
  141. data/lib/generators/seams/billing/templates/app/controllers/checkout_controller.rb.tt +92 -0
  142. data/lib/generators/seams/billing/templates/app/controllers/invoices_controller.rb.tt +63 -0
  143. data/lib/generators/seams/billing/templates/app/controllers/plans_controller.rb.tt +14 -0
  144. data/lib/generators/seams/billing/templates/app/controllers/portal_controller.rb.tt +45 -0
  145. data/lib/generators/seams/billing/templates/app/controllers/subscriptions_controller.rb.tt +119 -0
  146. data/lib/generators/seams/billing/templates/app/controllers/webhooks_controller.rb.tt +98 -0
  147. data/lib/generators/seams/billing/templates/app/helpers/currency_helper.rb.tt +44 -0
  148. data/lib/generators/seams/billing/templates/app/jobs/application_job.rb.tt +6 -0
  149. data/lib/generators/seams/billing/templates/app/jobs/cancel_subscription_job.rb.tt +39 -0
  150. data/lib/generators/seams/billing/templates/app/jobs/start_subscription_job.rb.tt +32 -0
  151. data/lib/generators/seams/billing/templates/app/jobs/webhooks/process_event_job.rb.tt +37 -0
  152. data/lib/generators/seams/billing/templates/app/models/application_record.rb.tt +7 -0
  153. data/lib/generators/seams/billing/templates/app/models/invoice.rb.tt +35 -0
  154. data/lib/generators/seams/billing/templates/app/models/lifetime_pass.rb.tt +60 -0
  155. data/lib/generators/seams/billing/templates/app/models/plan.rb.tt +95 -0
  156. data/lib/generators/seams/billing/templates/app/models/subscription.rb.tt +31 -0
  157. data/lib/generators/seams/billing/templates/app/models/webhook_event.rb.tt +13 -0
  158. data/lib/generators/seams/billing/templates/app/services/checkout_session_service.rb.tt +25 -0
  159. data/lib/generators/seams/billing/templates/app/services/customers/find_or_create_service.rb.tt +73 -0
  160. data/lib/generators/seams/billing/templates/app/services/invoices/sync_service.rb.tt +50 -0
  161. data/lib/generators/seams/billing/templates/app/services/lifetime/create_lifetime_session_service.rb.tt +82 -0
  162. data/lib/generators/seams/billing/templates/app/services/lifetime/create_pass_from_checkout_service.rb.tt +88 -0
  163. data/lib/generators/seams/billing/templates/app/services/lifetime/grant_pass_service.rb.tt +80 -0
  164. data/lib/generators/seams/billing/templates/app/services/lifetime/revoke_pass_service.rb.tt +59 -0
  165. data/lib/generators/seams/billing/templates/app/services/portal_session_service.rb.tt +23 -0
  166. data/lib/generators/seams/billing/templates/app/services/service_result.rb.tt +38 -0
  167. data/lib/generators/seams/billing/templates/app/services/stripe_service.rb.tt +67 -0
  168. data/lib/generators/seams/billing/templates/app/services/subscriptions/cancel_service.rb.tt +42 -0
  169. data/lib/generators/seams/billing/templates/app/services/subscriptions/change_plan_service.rb.tt +48 -0
  170. data/lib/generators/seams/billing/templates/app/services/subscriptions/reactivate_service.rb.tt +28 -0
  171. data/lib/generators/seams/billing/templates/app/services/webhooks/event_router.rb.tt +54 -0
  172. data/lib/generators/seams/billing/templates/app/services/webhooks/handler.rb.tt +93 -0
  173. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/charge_refunded_handler.rb.tt +18 -0
  174. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/checkout_session_completed_handler.rb.tt +58 -0
  175. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/invoice_created_handler.rb.tt +16 -0
  176. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/invoice_finalized_handler.rb.tt +14 -0
  177. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/invoice_handler_base.rb.tt +80 -0
  178. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/invoice_paid_handler.rb.tt +12 -0
  179. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/invoice_payment_failed_handler.rb.tt +12 -0
  180. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/invoice_voided_handler.rb.tt +12 -0
  181. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/payment_failed_handler.rb.tt +15 -0
  182. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/payment_succeeded_handler.rb.tt +19 -0
  183. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/subscription_created_handler.rb.tt +11 -0
  184. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/subscription_deleted_handler.rb.tt +15 -0
  185. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/subscription_handler_base.rb.tt +92 -0
  186. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/subscription_trial_will_end_handler.rb.tt +15 -0
  187. data/lib/generators/seams/billing/templates/app/services/webhooks/handlers/subscription_updated_handler.rb.tt +11 -0
  188. data/lib/generators/seams/billing/templates/app/views/admin/lifetime_passes/index.html.erb.tt +36 -0
  189. data/lib/generators/seams/billing/templates/app/views/admin/lifetime_passes/new.html.erb.tt +37 -0
  190. data/lib/generators/seams/billing/templates/app/views/checkout/success.html.erb.tt +5 -0
  191. data/lib/generators/seams/billing/templates/app/views/invoices/index.html.erb.tt +22 -0
  192. data/lib/generators/seams/billing/templates/app/views/invoices/show.html.erb.tt +14 -0
  193. data/lib/generators/seams/billing/templates/app/views/plans/index.html.erb.tt +51 -0
  194. data/lib/generators/seams/billing/templates/app/views/subscriptions/index.html.erb.tt +16 -0
  195. data/lib/generators/seams/billing/templates/app/views/subscriptions/show.html.erb.tt +25 -0
  196. data/lib/generators/seams/billing/templates/config/routes.rb.tt +39 -0
  197. data/lib/generators/seams/billing/templates/db/migrate/create_billing_invoices.rb.tt +32 -0
  198. data/lib/generators/seams/billing/templates/db/migrate/create_billing_lifetime_passes.rb.tt +43 -0
  199. data/lib/generators/seams/billing/templates/db/migrate/create_billing_plans.rb.tt +31 -0
  200. data/lib/generators/seams/billing/templates/db/migrate/create_billing_subscriptions.rb.tt +33 -0
  201. data/lib/generators/seams/billing/templates/db/migrate/create_billing_webhook_events.rb.tt +24 -0
  202. data/lib/generators/seams/billing/templates/lib/billing.rb.tt +34 -0
  203. data/lib/generators/seams/billing/templates/lib/concerns/billable.rb.tt +100 -0
  204. data/lib/generators/seams/billing/templates/lib/configuration.rb.tt +52 -0
  205. data/lib/generators/seams/billing/templates/lib/engine.rb.tt +72 -0
  206. data/lib/generators/seams/billing/templates/lib/gateways/abstract.rb.tt +65 -0
  207. data/lib/generators/seams/billing/templates/lib/gateways/adyen.rb.tt +16 -0
  208. data/lib/generators/seams/billing/templates/lib/gateways/paddle.rb.tt +22 -0
  209. data/lib/generators/seams/billing/templates/lib/gateways/stripe.rb.tt +155 -0
  210. data/lib/generators/seams/billing/templates/lib/stripe/client.rb.tt +101 -0
  211. data/lib/generators/seams/billing/templates/lib/stripe/webhook_signature.rb.tt +43 -0
  212. data/lib/generators/seams/billing/templates/lib/tasks/billing_check.rake.tt +34 -0
  213. data/lib/generators/seams/billing/templates/spec/factories/billing.rb.tt +65 -0
  214. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/charge_refunded.json.tt +19 -0
  215. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/checkout_session_completed.json.tt +17 -0
  216. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/customer_subscription_created.json.tt +25 -0
  217. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/customer_subscription_deleted.json.tt +17 -0
  218. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/customer_subscription_trial_will_end.json.tt +17 -0
  219. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/customer_subscription_updated.json.tt +28 -0
  220. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/invoice_created.json.tt +18 -0
  221. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/invoice_finalized.json.tt +18 -0
  222. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/invoice_paid.json.tt +19 -0
  223. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/invoice_payment_failed.json.tt +20 -0
  224. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/invoice_voided.json.tt +18 -0
  225. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/payment_intent_payment_failed.json.tt +21 -0
  226. data/lib/generators/seams/billing/templates/spec/fixtures/stripe/payment_intent_succeeded.json.tt +17 -0
  227. data/lib/generators/seams/billing/templates/spec/gateways/contract_spec.rb.tt +11 -0
  228. data/lib/generators/seams/billing/templates/spec/gateways/stripe_spec.rb.tt +53 -0
  229. data/lib/generators/seams/billing/templates/spec/models/plan_spec.rb.tt +81 -0
  230. data/lib/generators/seams/billing/templates/spec/models/subscription_spec.rb.tt +43 -0
  231. data/lib/generators/seams/billing/templates/spec/runtime/boot_spec.rb.tt +38 -0
  232. data/lib/generators/seams/billing/templates/spec/runtime/webhook_handlers_spec.rb.tt +382 -0
  233. data/lib/generators/seams/billing/templates/spec/support/shared_examples/a_billing_gateway.rb.tt +100 -0
  234. data/lib/generators/seams/billing/templates/spec/support/stripe_helpers.rb.tt +59 -0
  235. data/lib/generators/seams/core/core_generator.rb +191 -0
  236. data/lib/generators/seams/core/templates/README.md.tt +45 -0
  237. data/lib/generators/seams/core/templates/app/controllers/concerns/has_current_attributes.rb.tt +71 -0
  238. data/lib/generators/seams/core/templates/app/models/application_record.rb.tt +7 -0
  239. data/lib/generators/seams/core/templates/app/models/audit_log.rb.tt +19 -0
  240. data/lib/generators/seams/core/templates/app/models/concerns/auditable.rb.tt +64 -0
  241. data/lib/generators/seams/core/templates/app/models/concerns/sluggable.rb.tt +53 -0
  242. data/lib/generators/seams/core/templates/app/models/concerns/soft_deletable.rb.tt +37 -0
  243. data/lib/generators/seams/core/templates/app/models/concerns/tenant_scoped.rb.tt +39 -0
  244. data/lib/generators/seams/core/templates/app/models/current.rb.tt +16 -0
  245. data/lib/generators/seams/core/templates/app/services/event_publisher.rb.tt +23 -0
  246. data/lib/generators/seams/core/templates/app/validators/email_format_validator.rb.tt +21 -0
  247. data/lib/generators/seams/core/templates/db/migrate/create_core_audit_logs.rb.tt +29 -0
  248. data/lib/generators/seams/core/templates/lib/core.rb.tt +8 -0
  249. data/lib/generators/seams/core/templates/lib/engine.rb.tt +28 -0
  250. data/lib/generators/seams/core/templates/spec/concerns/auditable_spec.rb.tt +39 -0
  251. data/lib/generators/seams/core/templates/spec/concerns/sluggable_spec.rb.tt +29 -0
  252. data/lib/generators/seams/core/templates/spec/models/audit_log_spec.rb.tt +22 -0
  253. data/lib/generators/seams/core/templates/spec/runtime/boot_spec.rb.tt +25 -0
  254. data/lib/generators/seams/core/templates/spec/validators/email_format_validator_spec.rb.tt +29 -0
  255. data/lib/generators/seams/engine/engine_generator.rb +165 -0
  256. data/lib/generators/seams/engine/templates/Gemfile.tt +19 -0
  257. data/lib/generators/seams/engine/templates/LICENSE.tt +21 -0
  258. data/lib/generators/seams/engine/templates/README.md.tt +40 -0
  259. data/lib/generators/seams/engine/templates/Rakefile.tt +14 -0
  260. data/lib/generators/seams/engine/templates/app/application_controller.rb.tt +6 -0
  261. data/lib/generators/seams/engine/templates/app/application_record.rb.tt +16 -0
  262. data/lib/generators/seams/engine/templates/config/locales/en.yml.tt +14 -0
  263. data/lib/generators/seams/engine/templates/config/routes.rb.tt +4 -0
  264. data/lib/generators/seams/engine/templates/gemspec.tt +20 -0
  265. data/lib/generators/seams/engine/templates/host_initializer.rb.tt +13 -0
  266. data/lib/generators/seams/engine/templates/lib/engine.rb.tt +27 -0
  267. data/lib/generators/seams/engine/templates/lib/root.rb.tt +7 -0
  268. data/lib/generators/seams/engine/templates/lib/version.rb.tt +5 -0
  269. data/lib/generators/seams/engine/templates/rubocop.yml.tt +55 -0
  270. data/lib/generators/seams/engine/templates/spec/example_spec.rb.tt +16 -0
  271. data/lib/generators/seams/engine/templates/spec/spec_helper.rb.tt +23 -0
  272. data/lib/generators/seams/install/install_generator.rb +211 -0
  273. data/lib/generators/seams/install/templates/Dockerfile.tt +52 -0
  274. data/lib/generators/seams/install/templates/Procfile.tt +14 -0
  275. data/lib/generators/seams/install/templates/bin_seams.tt +107 -0
  276. data/lib/generators/seams/install/templates/ci.yml.tt +123 -0
  277. data/lib/generators/seams/install/templates/deploy.yml.tt +63 -0
  278. data/lib/generators/seams/install/templates/doc/ARCHITECTURE.md.tt +86 -0
  279. data/lib/generators/seams/install/templates/docker-entrypoint.tt +27 -0
  280. data/lib/generators/seams/install/templates/rubocop.yml.tt +33 -0
  281. data/lib/generators/seams/install/templates/ruby-version.tt +1 -0
  282. data/lib/generators/seams/install/templates/script/collate_coverage.rb.tt +33 -0
  283. data/lib/generators/seams/install/templates/script/run_affected_tests.sh.tt +64 -0
  284. data/lib/generators/seams/install/templates/seams.rake.tt +65 -0
  285. data/lib/generators/seams/install/templates/seams.rb.tt +9 -0
  286. data/lib/generators/seams/install/templates/seams_engines.rb.tt +15 -0
  287. data/lib/generators/seams/notifications/notifications_generator.rb +395 -0
  288. data/lib/generators/seams/notifications/templates/README.md.tt +269 -0
  289. data/lib/generators/seams/notifications/templates/app/channels/notification_channel.rb.tt +36 -0
  290. data/lib/generators/seams/notifications/templates/app/controllers/notifications_controller.rb.tt +58 -0
  291. data/lib/generators/seams/notifications/templates/app/controllers/preferences_controller.rb.tt +54 -0
  292. data/lib/generators/seams/notifications/templates/app/javascript/controllers/notification_bell_controller.js.tt +34 -0
  293. data/lib/generators/seams/notifications/templates/app/jobs/application_job.rb.tt +6 -0
  294. data/lib/generators/seams/notifications/templates/app/jobs/create_notification_job.rb.tt +31 -0
  295. data/lib/generators/seams/notifications/templates/app/jobs/send_due_notifications_job.rb.tt +22 -0
  296. data/lib/generators/seams/notifications/templates/app/jobs/send_notification_job.rb.tt +13 -0
  297. data/lib/generators/seams/notifications/templates/app/mailers/application_mailer.rb.tt +12 -0
  298. data/lib/generators/seams/notifications/templates/app/mailers/notification_mailer.rb.tt +23 -0
  299. data/lib/generators/seams/notifications/templates/app/models/application_record.rb.tt +7 -0
  300. data/lib/generators/seams/notifications/templates/app/models/delivery.rb.tt +13 -0
  301. data/lib/generators/seams/notifications/templates/app/models/notification.rb.tt +218 -0
  302. data/lib/generators/seams/notifications/templates/app/models/notification_preference.rb.tt +29 -0
  303. data/lib/generators/seams/notifications/templates/app/models/strategies/email.rb.tt +38 -0
  304. data/lib/generators/seams/notifications/templates/app/models/strategies/in_app.rb.tt +26 -0
  305. data/lib/generators/seams/notifications/templates/app/models/strategies/sms.rb.tt +33 -0
  306. data/lib/generators/seams/notifications/templates/app/subscribers/auth_subscriber.rb.tt +71 -0
  307. data/lib/generators/seams/notifications/templates/app/subscribers/billing_subscriber.rb.tt +127 -0
  308. data/lib/generators/seams/notifications/templates/app/views/layouts/notifications/mailer.html.erb.tt +22 -0
  309. data/lib/generators/seams/notifications/templates/app/views/layouts/notifications/mailer.text.erb.tt +4 -0
  310. data/lib/generators/seams/notifications/templates/app/views/notifications/_bell.html.erb.tt +15 -0
  311. data/lib/generators/seams/notifications/templates/app/views/notifications/index.html.erb.tt +15 -0
  312. data/lib/generators/seams/notifications/templates/app/views/templates/billing/invoice_failed.html.erb.tt +4 -0
  313. data/lib/generators/seams/notifications/templates/app/views/templates/billing/invoice_failed.text.erb.tt +4 -0
  314. data/lib/generators/seams/notifications/templates/app/views/templates/billing/invoice_paid.html.erb.tt +3 -0
  315. data/lib/generators/seams/notifications/templates/app/views/templates/billing/invoice_paid.text.erb.tt +3 -0
  316. data/lib/generators/seams/notifications/templates/app/views/templates/billing/lifetime_granted.html.erb.tt +5 -0
  317. data/lib/generators/seams/notifications/templates/app/views/templates/billing/lifetime_granted.text.erb.tt +5 -0
  318. data/lib/generators/seams/notifications/templates/app/views/templates/billing/lifetime_purchased.html.erb.tt +5 -0
  319. data/lib/generators/seams/notifications/templates/app/views/templates/billing/lifetime_purchased.text.erb.tt +5 -0
  320. data/lib/generators/seams/notifications/templates/app/views/templates/billing/subscription_canceled.html.erb.tt +4 -0
  321. data/lib/generators/seams/notifications/templates/app/views/templates/billing/subscription_canceled.text.erb.tt +4 -0
  322. data/lib/generators/seams/notifications/templates/app/views/templates/billing/subscription_started.html.erb.tt +4 -0
  323. data/lib/generators/seams/notifications/templates/app/views/templates/billing/subscription_started.text.erb.tt +5 -0
  324. data/lib/generators/seams/notifications/templates/app/views/templates/billing/subscription_updated.html.erb.tt +3 -0
  325. data/lib/generators/seams/notifications/templates/app/views/templates/billing/subscription_updated.text.erb.tt +3 -0
  326. data/lib/generators/seams/notifications/templates/app/views/templates/default.html.erb.tt +10 -0
  327. data/lib/generators/seams/notifications/templates/app/views/templates/default.text.erb.tt +11 -0
  328. data/lib/generators/seams/notifications/templates/app/views/templates/welcome.html.erb.tt +6 -0
  329. data/lib/generators/seams/notifications/templates/app/views/templates/welcome.text.erb.tt +6 -0
  330. data/lib/generators/seams/notifications/templates/config/initializers/notifications.rb.tt +58 -0
  331. data/lib/generators/seams/notifications/templates/config/routes.rb.tt +17 -0
  332. data/lib/generators/seams/notifications/templates/db/migrate/create_notification_deliveries.rb.tt +16 -0
  333. data/lib/generators/seams/notifications/templates/db/migrate/create_notification_preferences.rb.tt +25 -0
  334. data/lib/generators/seams/notifications/templates/db/migrate/create_notifications.rb.tt +35 -0
  335. data/lib/generators/seams/notifications/templates/lib/adapters/abstract.rb.tt +20 -0
  336. data/lib/generators/seams/notifications/templates/lib/adapters/action_mailer.rb.tt +17 -0
  337. data/lib/generators/seams/notifications/templates/lib/adapters/null_sms.rb.tt +23 -0
  338. data/lib/generators/seams/notifications/templates/lib/concerns/notifiable.rb.tt +135 -0
  339. data/lib/generators/seams/notifications/templates/lib/configuration.rb.tt +24 -0
  340. data/lib/generators/seams/notifications/templates/lib/engine.rb.tt +35 -0
  341. data/lib/generators/seams/notifications/templates/lib/notifications.rb.tt +75 -0
  342. data/lib/generators/seams/notifications/templates/lib/type_registry.rb.tt +74 -0
  343. data/lib/generators/seams/notifications/templates/spec/factories/notifications.rb.tt +53 -0
  344. data/lib/generators/seams/notifications/templates/spec/models/delivery_spec.rb.tt +28 -0
  345. data/lib/generators/seams/notifications/templates/spec/models/notification_preference_spec.rb.tt +46 -0
  346. data/lib/generators/seams/notifications/templates/spec/models/notification_spec.rb.tt +60 -0
  347. data/lib/generators/seams/notifications/templates/spec/runtime/bell_broadcast_spec.rb.tt +59 -0
  348. data/lib/generators/seams/notifications/templates/spec/runtime/billing_subscriber_skip_spec.rb.tt +87 -0
  349. data/lib/generators/seams/notifications/templates/spec/runtime/boot_spec.rb.tt +39 -0
  350. data/lib/generators/seams/notifications/templates/spec/runtime/schedule_round_trip_spec.rb.tt +55 -0
  351. data/lib/generators/seams/remove/remove_generator.rb +259 -0
  352. data/lib/generators/seams/teams/teams_generator.rb +298 -0
  353. data/lib/generators/seams/teams/templates/README.md.tt +88 -0
  354. data/lib/generators/seams/teams/templates/app/controllers/invitations_controller.rb.tt +102 -0
  355. data/lib/generators/seams/teams/templates/app/controllers/memberships_controller.rb.tt +54 -0
  356. data/lib/generators/seams/teams/templates/app/controllers/teams_controller.rb.tt +68 -0
  357. data/lib/generators/seams/teams/templates/app/jobs/application_job.rb.tt +6 -0
  358. data/lib/generators/seams/teams/templates/app/mailers/invitation_mailer.rb.tt +34 -0
  359. data/lib/generators/seams/teams/templates/app/models/application_record.rb.tt +7 -0
  360. data/lib/generators/seams/teams/templates/app/models/current.rb.tt +30 -0
  361. data/lib/generators/seams/teams/templates/app/models/invitation.rb.tt +36 -0
  362. data/lib/generators/seams/teams/templates/app/models/membership.rb.tt +36 -0
  363. data/lib/generators/seams/teams/templates/app/models/team.rb.tt +32 -0
  364. data/lib/generators/seams/teams/templates/app/subscribers/invitation_subscriber.rb.tt +36 -0
  365. data/lib/generators/seams/teams/templates/app/views/invitation_mailer/invite.text.erb.tt +8 -0
  366. data/lib/generators/seams/teams/templates/app/views/invitations/index.html.erb.tt +44 -0
  367. data/lib/generators/seams/teams/templates/app/views/memberships/index.html.erb.tt +32 -0
  368. data/lib/generators/seams/teams/templates/app/views/teams/edit.html.erb.tt +28 -0
  369. data/lib/generators/seams/teams/templates/app/views/teams/index.html.erb.tt +15 -0
  370. data/lib/generators/seams/teams/templates/app/views/teams/new.html.erb.tt +24 -0
  371. data/lib/generators/seams/teams/templates/app/views/teams/show.html.erb.tt +17 -0
  372. data/lib/generators/seams/teams/templates/config/routes.rb.tt +19 -0
  373. data/lib/generators/seams/teams/templates/db/migrate/create_team_invitations.rb.tt +24 -0
  374. data/lib/generators/seams/teams/templates/db/migrate/create_team_memberships.rb.tt +25 -0
  375. data/lib/generators/seams/teams/templates/db/migrate/create_teams.rb.tt +18 -0
  376. data/lib/generators/seams/teams/templates/lib/concerns/account_scoped.rb.tt +79 -0
  377. data/lib/generators/seams/teams/templates/lib/concerns/authorization.rb.tt +55 -0
  378. data/lib/generators/seams/teams/templates/lib/configuration.rb.tt +45 -0
  379. data/lib/generators/seams/teams/templates/lib/engine.rb.tt +51 -0
  380. data/lib/generators/seams/teams/templates/lib/teams.rb.tt +22 -0
  381. data/lib/generators/seams/teams/templates/spec/factories/teams.rb.tt +47 -0
  382. data/lib/generators/seams/teams/templates/spec/models/invitation_spec.rb.tt +25 -0
  383. data/lib/generators/seams/teams/templates/spec/models/membership_spec.rb.tt +29 -0
  384. data/lib/generators/seams/teams/templates/spec/models/team_spec.rb.tt +23 -0
  385. data/lib/generators/seams/teams/templates/spec/runtime/boot_spec.rb.tt +32 -0
  386. data/lib/seams/cli/list.rb +111 -0
  387. data/lib/seams/cli/quality.rb +99 -0
  388. data/lib/seams/cli/resolve.rb +276 -0
  389. data/lib/seams/cli/test_changed.rb +116 -0
  390. data/lib/seams/cli.rb +48 -0
  391. data/lib/seams/configuration.rb +19 -0
  392. data/lib/seams/cops/known_queue_names.rb +42 -0
  393. data/lib/seams/cops/migration_comments.rb +68 -0
  394. data/lib/seams/cops/no_cross_engine_dependency.rb +58 -0
  395. data/lib/seams/cops/no_cross_engine_model_access.rb +153 -0
  396. data/lib/seams/cops.rb +18 -0
  397. data/lib/seams/event_registry.rb +49 -0
  398. data/lib/seams/events/adapter.rb +24 -0
  399. data/lib/seams/events/adapters/active_support.rb +31 -0
  400. data/lib/seams/events/publisher.rb +178 -0
  401. data/lib/seams/events.rb +39 -0
  402. data/lib/seams/generators/dummy_app_writer.rb +424 -0
  403. data/lib/seams/generators/eject_aware.rb +102 -0
  404. data/lib/seams/generators/follow_up_generator.rb +148 -0
  405. data/lib/seams/generators/host_injector.rb +124 -0
  406. data/lib/seams/generators/sibling_rubocop_writer.rb +77 -0
  407. data/lib/seams/generators/splicer.rb +217 -0
  408. data/lib/seams/observability/adapter.rb +33 -0
  409. data/lib/seams/observability/adapters/rails_logger.rb +59 -0
  410. data/lib/seams/observability.rb +34 -0
  411. data/lib/seams/runtime.rb +23 -0
  412. data/lib/seams/version.rb +5 -0
  413. data/lib/seams.rb +23 -0
  414. metadata +493 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 48050ae5ddd2075cf436343c837ad75370660410f96c3a3d1c12e4d58612ec65
4
+ data.tar.gz: debc50e9f6570fa7361e8a03d23bab7c1c84e30214cb4b49ff2e66b957e493d9
5
+ SHA512:
6
+ metadata.gz: bd7f31ec043899f985949285a8f3b47cfd9fda83885d06c9f89fc5052c7374113427c054c7868501c34d484ae62c4f58377d915300777df0ff150ea7d34068b4
7
+ data.tar.gz: ae8884205c3f95c991722517358897b1bb5ee559be3bca06d513f477e76e58fbb8bfeb4a20602be40517d51a8178e7e1d0cd2e744e069eefd1cae5b6950afa6e
data/CHANGELOG.md ADDED
@@ -0,0 +1,335 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] — 2026-05-10
11
+
12
+ First public release on rubygems.org. The cumulative changelog from
13
+ Wave 1 through Wave 11A follows. Subsequent releases will track
14
+ per-version changes only.
15
+
16
+ ### Wave 11A — Admin engine (Administrate-backed)
17
+
18
+ Ships `bin/rails generate seams:admin` as an opt-in canonical engine.
19
+ Hosts that have the canonical six in place (core, auth, accounts,
20
+ notifications, billing, teams) can mount an Administrate-backed admin
21
+ surface at `/admin` covering all twelve canonical seams models with a
22
+ single command. Dashboards, two-mode authorization, audit-log
23
+ auto-write, and the four config knobs all ship out of the box. See
24
+ [`doc/ARCHITECTURE_WAVE_11.md`](doc/ARCHITECTURE_WAVE_11.md) for the
25
+ new architecture material; the framework selection rationale lives in
26
+ [`proposals/admin_engine_administrate.md`](proposals/admin_engine_administrate.md).
27
+
28
+ #### Added
29
+
30
+ - **`bin/seams admin` generator + canonical engine.** Writes an
31
+ `engines/admin/` engine into the host with twelve Administrate
32
+ dashboards covering `Auth::Identity`, `Accounts::Account`,
33
+ `Accounts::Membership`, `Teams::Team`, `Teams::Membership`,
34
+ `Teams::Invitation`, `Notifications::Notification`,
35
+ `Notifications::NotificationPreference`, `Billing::Plan`,
36
+ `Billing::Subscription`, `Billing::Invoice`, and
37
+ `Billing::LifetimePass`. Each dashboard subclasses
38
+ `Administrate::BaseDashboard`; each controller subclasses
39
+ `Seams::Admin::ApplicationController` (NOT Administrate's directly)
40
+ so it inherits the gate, the `pundit_user` hook, and the audit-log
41
+ auto-write. Engine ships **no migrations** — read-only over existing
42
+ tables.
43
+ - **Two-mode authorization via Pundit `policy_namespace`.** Twelve
44
+ policies under `Admin::Platform::*` (gate: `Auth::Identity#staff?`,
45
+ no tenant filter) and twelve under `Admin::Tenant::*` (gate:
46
+ `Accounts::Membership#role == "admin"`, scope filtered by
47
+ `account_id` from `Accounts::Current.membership`). Plus two base
48
+ `ApplicationPolicy` classes — 26 policy files total.
49
+ `Seams::Admin.config.tenancy_scope` (`:platform` default, `:tenant`
50
+ alternative) selects the namespace at request time.
51
+ - **`Seams::Admin::Context` Struct.** Wraps the current Identity +
52
+ Membership as the value `pundit_user` returns. Exposes nil-safe
53
+ `staff?`, `role`, and `account_id` convenience methods so policies
54
+ stay readable without each one fishing values out of the controller.
55
+ - **Audit-log auto-write via `Core::Auditable` integration.**
56
+ `record_admin_audit` after_action on every successful
57
+ create/update/destroy emits a `Core::AuditLog` row keyed on
58
+ `Auth::Current.identity&.id`. Wrapped in `defined?(Core::AuditLog)`
59
+ so the engine boots without core. Update payloads carry
60
+ `record.saved_changes.transform_values(&:last)`; create/destroy
61
+ payloads carry attributes minus timestamps.
62
+ - **Four configuration knobs** in `Seams::Admin.config`:
63
+ `authenticator` (callable; default `staff?` on current Identity);
64
+ `tenancy_scope` (`:platform` | `:tenant`); `theme_css_path`
65
+ (host-supplied admin restyle path); `before_admin_action` (callable
66
+ hook for 2FA, IP allow-list, etc.).
67
+ - **Five Wave-10 insertion-point markers** placed in the admin engine:
68
+ `admin.engine.events`, `admin.routes.before_resources`,
69
+ `admin.routes.after_resources`, `admin.configuration.attributes`,
70
+ `admin.configuration.defaults`. Catalogue updated to 38 markers
71
+ total across seven engines.
72
+ - **Showcase install path on top of `seams-example`.** The admin
73
+ generator stub-loads `Auth::Current` and `Accounts::Current`
74
+ CurrentAttributes objects in the dummy app, ships slim
75
+ `ApplicationRecord` stubs for every dashboard's resource_class, and
76
+ appends `administrate` + `pundit` to both the engine's standalone
77
+ Gemfile and the host Gemfile.
78
+ - **Boot-time dependency assertion.** The engine raises a clear
79
+ `[seams admin] missing required dependency: ...` at boot when
80
+ `Auth::Identity`, `Administrate`, or `Pundit` is missing — fail
81
+ loud at boot rather than NameError mid-request.
82
+ - **`bin/seams help` + post-install message** updated to list `admin`
83
+ alongside the canonical generators (with the explicit "optional —
84
+ generate after the canonical six" caveat).
85
+ - **AdminUser-on-separate-tables rule reinterpretation** documented
86
+ inline in the engine README. Wave 9's credential-only
87
+ `Auth::Identity` already satisfies the rule's intent (no
88
+ customer-facing concerns on the admin authentication object); a
89
+ boolean `staff?` flag is the right granularity. Hosts that need
90
+ hard isolation override the authenticator.
91
+
92
+ ### Wave 10 — Splicing tooling
93
+
94
+ Turns seams from a one-shot scaffolder into a long-lived framework.
95
+ Generated engines now expose stable, named extension points;
96
+ follow-up generators target those points to add features without
97
+ re-templating the whole engine; and `bin/seams resolve --eject`
98
+ marks any single host file as host-owned so subsequent
99
+ `bin/seams <engine>` runs leave it alone. See
100
+ [`doc/ARCHITECTURE_WAVE_10.md`](doc/ARCHITECTURE_WAVE_10.md) for the
101
+ addendum and [`doc/WRITING_FOLLOW_UP_GENERATORS.md`](doc/WRITING_FOLLOW_UP_GENERATORS.md)
102
+ for the author's guide.
103
+
104
+ #### Added
105
+
106
+ - **Insertion-point machinery.** `Seams::Generators::Splicer`
107
+ (idempotent splice primitives — looks up markers by name, never by
108
+ line number; auto-detects indentation off the marker line; fifty-line
109
+ idempotency window) and `Seams::Generators::FollowUpGenerator`
110
+ (Rails generator base class supplying `engine_path`, `splice`,
111
+ `assert_marker_exists!`, and a `report_summary` template-method
112
+ hook). Pure file I/O — no Rails dep on the Splicer itself, so
113
+ `bin/seams resolve` can reuse it without booting Rails.
114
+ - **Insertion-point catalogue.** 33 markers placed across the six
115
+ canonical engines (32 active + 1 deferred to Wave 12 pending the
116
+ core Configuration class). Marker shape:
117
+ `# seams:insertion-point <engine>.<area>.<scope>` — ASCII only,
118
+ greppable, parses through every Ruby linter. Format spec in
119
+ [`doc/INSERTION_POINTS.md`](doc/INSERTION_POINTS.md); canonical list
120
+ in [`doc/INSERTION_POINTS_CATALOGUE.md`](doc/INSERTION_POINTS_CATALOGUE.md).
121
+ - **`bin/seams resolve` CLI.** Three modes:
122
+ - `--eject <engine>/<file>` — prepends a
123
+ `# seams:ejected from <engine>.<path>` header to the host file;
124
+ refuses to eject framework-managed files (migrations, engine.rb,
125
+ version.rb, Gemfile, .gemspec).
126
+ - `--list-markers <engine>` — lists every insertion-point marker
127
+ the engine ships, with file:line and the catalogue's "purpose"
128
+ one-liner where present. Falls back to a "this engine may not
129
+ have been retrofitted" hint when the engine has zero markers.
130
+ - `--list-ejected` — surveys `engines/` for files carrying the
131
+ eject header, prints them with their source marker.
132
+ - **`Seams::Generators::EjectAware` mixin** — wired into all six
133
+ canonical engine generators (auth, accounts, billing, core,
134
+ notifications, teams). Every `template` call now goes through
135
+ `template_unless_ejected`, which detects the eject header in the
136
+ destination's first 200 bytes and short-circuits with a yellow
137
+ `skip` log line.
138
+ - **First showcase follow-up generator.**
139
+ `bin/rails generate seams:auth:add_oauth_provider <name>` (e.g.
140
+ `linkedin`, `apple`, `microsoft`) creates an
141
+ `Auth::OAuth::<Provider>` adapter under
142
+ `engines/auth/lib/auth/oauth/<name>.rb`, splices a configuration
143
+ entry into `engines/auth/lib/auth/configuration.rb` at the
144
+ `auth.configuration.oauth_providers` marker, and writes a matching
145
+ spec. Idempotent on rerun.
146
+ - **Documentation.**
147
+ [`doc/INSERTION_POINTS.md`](doc/INSERTION_POINTS.md) (format spec),
148
+ [`doc/INSERTION_POINTS_CATALOGUE.md`](doc/INSERTION_POINTS_CATALOGUE.md)
149
+ (canonical 33-marker list),
150
+ [`doc/WRITING_FOLLOW_UP_GENERATORS.md`](doc/WRITING_FOLLOW_UP_GENERATORS.md)
151
+ (author's guide), and
152
+ [`doc/ARCHITECTURE_WAVE_10.md`](doc/ARCHITECTURE_WAVE_10.md)
153
+ (architecture addendum with splice + eject sequence diagrams).
154
+ - **Host-facing surfaces updated.**
155
+ `bin/seams help` and `bin/seams resolve --help` document the new
156
+ resolve modes; the install generator's post-install message lists
157
+ the resolve sub-commands and points at the showcase follow-up
158
+ generator.
159
+
160
+ ### Wave 9 — Identity / Account / Team rework (BREAKING)
161
+
162
+ Replaces the conflated `Auth::User` (which owned credentials AND
163
+ tenant-membership concepts) with three peer engines, each with one
164
+ clear responsibility. See `doc/UPGRADING_FROM_WAVE_8.md` for the
165
+ migration story.
166
+
167
+ #### Added
168
+
169
+ - New `accounts` engine. Owns `Accounts::Account` (the tenant) and
170
+ `Accounts::Membership` (Identity ↔ Account, role enum:
171
+ owner/admin/member/system). Provides `Accounts::Current.account`
172
+ and `Accounts::Current.membership` (the matching membership
173
+ auto-derived for the signed-in identity), `Accounts::AccountScoped`
174
+ concern (default-scope to the current account), and an
175
+ auto-created `system` Membership per Account so audit-log writes
176
+ from background jobs always have a valid actor to point at.
177
+ - `Accounts::Authorization` controller concern with default-on
178
+ `ensure_account_access`; opt out via `disallow_account_scope` or
179
+ `require_access_without_membership`. Helpers `ensure_admin` and
180
+ `ensure_staff` for admin-tooling guards.
181
+ - New `Auth::Current` per-request namespace (peer to
182
+ `Accounts::Current`, `Teams::Current`, and `Core::Current`). The
183
+ Auth engine sets `Auth::Current.identity` in its session lookup;
184
+ the rest of the engines read it.
185
+ - New `Teams::Current` per-request namespace, peer to
186
+ `Auth::Current` and `Accounts::Current`. `Teams::AccountScoped`
187
+ reads `Teams::Current.team` to scope rows to the current team.
188
+ - New `bin/seams accounts` command and Accounts engine generator.
189
+
190
+ #### Changed (BREAKING)
191
+
192
+ - `Auth::User` renamed to `Auth::Identity`. The `auth_users` table
193
+ becomes `auth_identities`. All credential state
194
+ (`password_digest`, OAuth grants, sessions, passkeys, magic-link
195
+ grants, API tokens) stays on `Auth::Identity` — the rename is
196
+ about meaning, not about splitting state.
197
+ - `Auth::Authentication` controller concern renamed `current_user`
198
+ to `current_identity` and `authenticate_user!` to
199
+ `authenticate_identity!`. Hosts that maintain a domain User on
200
+ top of `Auth::Identity` can re-expose `current_user` via their
201
+ own concern.
202
+ - The Rails-8 `has_secure_password` `reset_token: false` workaround
203
+ is dropped — the rename to `Auth::Identity` resolves the prior
204
+ naming clash on `password_reset_token`.
205
+ - `Teams::Membership` joins `Auth::Identity` directly (column
206
+ `identity_id`), not the host User. The `Teams::Teamable` concern
207
+ is removed entirely (Wave 9 dropped the canonical demo's host
208
+ User; nowhere to mix it into).
209
+ - `Team#member?` signature changed: previously took an
210
+ `Auth::User`-like record; now takes an `identity_id` integer.
211
+ Callers that passed a record need to pass `record.id` instead.
212
+ - Notifications subscribers re-target Identity/Account, not host
213
+ User:
214
+ - `Notifications::AuthSubscriber` reads `identity_id` from the
215
+ `identity.signed_up.auth` event payload.
216
+ - `Notifications::BillingSubscriber` resolves the owner by reading
217
+ `Billing.configuration.billable_class` (default
218
+ `Accounts::Account`) and looking up the row by `account_id`
219
+ carried on the billing event payload.
220
+ - `Notifications::PreferencesController` reads/writes
221
+ `notification_preferences.identity_id` (renamed from `user_id`).
222
+ - `Notifications::NotificationsController` and
223
+ `Notifications::NotificationChannel` resolve the recipient via
224
+ `Auth::Current.identity`, with a legacy `current_user` fallback
225
+ for hosts that maintain a domain User.
226
+ - `Billing.configuration.billable_class` defaults to
227
+ `"Accounts::Account"` (was `"User"`). The engine constantizes
228
+ lazily so hosts can flip this at runtime.
229
+ - Auth engine event names renamed:
230
+ - `user.signed_up.auth` → `identity.signed_up.auth`
231
+ - `user.signed_in.auth` → `identity.signed_in.auth`
232
+ - `user.signed_out.auth` → `identity.signed_out.auth`
233
+ Event payload keys renamed: `user_id:` → `identity_id:`.
234
+ - Teams engine event names renamed:
235
+ - `team.member_added.teams` → `team.member_joined.teams`
236
+ - `team.member_removed.teams` → `team.member_left.teams`
237
+ - Drop host `User` model from the canonical demo. Hosts that want
238
+ a domain-specific User keep their own; pure SaaS hosts don't need
239
+ one.
240
+
241
+ #### Fixed
242
+
243
+ - `Seams/NoCrossEngineModelAccess` cop relaxed: every engine ships
244
+ its own `<Engine>::Current` namespace, and these per-request
245
+ state holders are intentionally readable from any engine. The
246
+ cop now treats `Current` as a framework-level constant and
247
+ exempts it from the boundary rule. Documented in
248
+ `doc/CURRENT_ATTRIBUTES.md` and inline in the cop's docstring.
249
+ - `Teams::AccountScoped` now references `Teams::Current.team`
250
+ (previously a bare `Current.team` that resolved to nothing
251
+ inside `module Teams` — silently making the default_scope a
252
+ no-op for every host that didn't define a top-level `Current`).
253
+ - `Teams::Authorization`, `TeamsController#current_identity_id`,
254
+ and `InvitationsController#current_identity_id` now reference
255
+ `Auth::Current.identity` (previously a bare `Current.identity`
256
+ that resolved to nothing — silently 403-ing every team
257
+ membership check).
258
+ - `Notifications::PreferencesController` queries
259
+ `identity_id` (was `user_id`, which the migration never
260
+ created — every GET / PATCH was raising
261
+ `ActiveRecord::StatementInvalid`).
262
+ - `Core::HasCurrentAttributes#resolve_current_user` now reads
263
+ `Auth::Current.identity` first (with a `current_identity` and
264
+ `current_user` fallback chain for hosts that ship a domain
265
+ User). Previously fell through to `current_user` only, which
266
+ the canonical Wave-9 host doesn't expose, so
267
+ `Core::Current.user` was always nil and `Core::Auditable` wrote
268
+ `actor_id = nil` on every audit row.
269
+ - `Core::HasCurrentAttributes#resolve_current_team` no longer
270
+ reaches into `Teams::Team` directly; reads `Teams::Current.team`
271
+ instead. Inverts the dependency direction: teams may include
272
+ core's concerns, but core must not know about teams' models.
273
+ Hosts that want a different binding (e.g. URL `params[:team_id]`)
274
+ override the method.
275
+ - `Accounts::AccountScoped` is now fail-closed: when
276
+ `Accounts::Current.account` is unset, the default_scope returns
277
+ no rows (was: returned every row across every tenant — the
278
+ canonical multi-tenant data-leak bug). New `with_no_account_scope`
279
+ class method as the documented opt-out for seed scripts and
280
+ platform-admin tooling. Same treatment for `Teams::AccountScoped`.
281
+ - `accounts_memberships` migration: partial unique index over
282
+ `(account_id) WHERE role = 'system'` enforces the documented
283
+ invariant of EXACTLY ONE system actor per Account at the DB
284
+ level. Postgres treats NULLs as distinct in unique indexes, so
285
+ the existing `(account_id, identity_id)` compound index didn't
286
+ prevent two `(account_id, NULL)` system rows.
287
+ - `Notifications::Notification#owner_id` is now a `string`
288
+ column (was bigint). Holds both bigint Identity IDs and UUID
289
+ Account IDs simultaneously — necessary now that the
290
+ BillingSubscriber addresses notifications at the
291
+ `Accounts::Account` (UUID PK).
292
+ - `Accounts::Engine` and `Teams::Engine` raise a clear
293
+ `[seams ...] missing required cross-engine dependency` error
294
+ at boot when their required peer (auth) isn't installed.
295
+ Previously failed silently at first query.
296
+ - Notifications and Accounts dummy schemas align on the
297
+ `auth_identities` shape (text email + password_digest + staff
298
+ flag + partial staff index).
299
+ - Removed dead `User < ApplicationRecord` model from the core
300
+ engine's dummy app — the auditable spec stubs its own `Article`
301
+ via `stub_const`; nothing else referenced the User class.
302
+
303
+ ### Pre-Wave-9 history
304
+
305
+ Waves 1–8 of the seams gem are summarised below. Detailed
306
+ per-commit history is in the git log; the published gem version
307
+ will be 0.9.0 covering Waves 1–9 cumulatively.
308
+
309
+ - **Wave 8** — Per-engine spec coverage harmonised; 4-agent audit
310
+ fixes; `bin/audit` consolidated as the single pre-push verification
311
+ command.
312
+ - **Wave 7** — End-to-end `spec/integration_full/` smoke probe
313
+ exercising every public seams API against a real `rails new`
314
+ host on Postgres.
315
+ - **Wave 6** — Replaced the in-house Faraday-based Stripe client
316
+ with the official `stripe` Ruby gem (cuts ~600 lines of adapter
317
+ code; Stripe gem now owns gateway evolution).
318
+ - **Wave 5** — Six-agent audit + risk-fix pass: 5 RISK-rated
319
+ defects across publisher contract, generator templates,
320
+ notifications adapter resolution, and CI YAML drift.
321
+ - **Wave 4** — Teams engine (Phases 4A.1 + 4A.2): Team /
322
+ Membership / Invitation models, controllers, views, mailer,
323
+ invitation accept flow with row-lock against double-clicks.
324
+ - **Wave 3** — Integration spec verifying billing + auth +
325
+ notifications wired together end-to-end (post-rails-new host).
326
+ - **Wave 2** — Notifications engine: STI strategies, ActionCable
327
+ bell, TypeRegistry, --channels flag.
328
+ - **Wave 1** — Auth engine + Billing engine + Core engine + the
329
+ custom RuboCop cops + the engine generator scaffold.
330
+
331
+ ## [0.0.1]
332
+
333
+ ### Added
334
+
335
+ - Initial gem skeleton: `Seams.configure`, `Seams::Configuration`, version constant.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 David Silva
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.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Seams
2
+
3
+ > A CLI framework that generates modular Rails engines.
4
+
5
+ Seams gives you the architectural benefits of microservices — clear
6
+ boundaries, independent testing, team autonomy — without the
7
+ operational cost. You ship a single Rails app. You think in
8
+ independent engines.
9
+
10
+ > Seams materialises the patterns David Silva teaches in **[Modular
11
+ > Rails: Architecture for the Long Game](https://davidslv.uk/modular-rails/)**.
12
+ > The book is the artefact; this gem is the executable shorthand. See
13
+ > [seams-example](https://github.com/Davidslv/seams-example) for a
14
+ > reference host that wires every canonical engine end-to-end.
15
+
16
+ ## Quick start
17
+
18
+ ```ruby
19
+ # Gemfile
20
+ gem "seams"
21
+ ```
22
+
23
+ ```bash
24
+ bundle install
25
+ bin/rails generate seams:install
26
+ bin/seams auth
27
+ bin/seams accounts
28
+ bin/seams notifications
29
+ bin/seams billing
30
+ bin/seams teams
31
+ bin/seams list
32
+ ```
33
+
34
+ That's auth, tenant boundary, transactional email/SMS, Stripe
35
+ subscriptions, and multi-tenant teams generated as five real Rails
36
+ engines under `engines/`. Every file is yours to edit. Nothing is
37
+ hidden behind the gem.
38
+
39
+ ## What you get
40
+
41
+ - `bin/seams install` — adds the framework + CI workflow + bin/seams wrapper
42
+ - `bin/seams engine <name>` — generic engine scaffold
43
+ - `bin/seams core` — canonical Core engine (Current attributes, AuditLog, TenantScoped, EmailFormatValidator)
44
+ - `bin/seams auth` — canonical Auth engine (Identity, Session, OAuth, API tokens, GDPR-encrypted PII)
45
+ - `bin/seams accounts` — canonical Accounts engine (Account tenant, Membership, AccountScoped, system actor)
46
+ - `bin/seams notifications` — canonical Notifications engine (STI strategies, ActionCable bell, TypeRegistry, --channels flag)
47
+ - `bin/seams billing` — canonical Billing engine (official Stripe gem, 13-handler webhook router, Lifetime Deals)
48
+ - `bin/seams teams` — canonical Teams engine (Team, Membership, Invitation, AccountScoped, --with flag)
49
+ - `bin/seams remove <name>` — clean removal + sibling cleanup + drop-table migration
50
+ - `bin/seams list` — engines, the events they emit, and what they subscribe to
51
+ - `bin/seams resolve` — eject host files / list insertion-point markers / list ejected files
52
+ - `bin/rails generate seams:auth:add_oauth_provider <name>` — first follow-up generator (adds an OAuth provider adapter to an installed Auth engine)
53
+ - Four custom RuboCop cops that enforce cross-engine boundaries
54
+ - A GitHub Actions CI workflow that runs every engine's specs in parallel
55
+
56
+ ## Documentation
57
+
58
+ - [doc/GETTING_STARTED.md](doc/GETTING_STARTED.md)
59
+ - [doc/ARCHITECTURE.md](doc/ARCHITECTURE.md) — short overview
60
+ - [doc/ARCHITECTURE_WAVE_9.md](doc/ARCHITECTURE_WAVE_9.md) — full system walk-through (post-Wave-9)
61
+ - [doc/ARCHITECTURE_WAVE_10.md](doc/ARCHITECTURE_WAVE_10.md) — Wave 10 addendum: insertion points, follow-up generators, eject CLI
62
+ - [doc/ENGINE_CATALOGUE.md](doc/ENGINE_CATALOGUE.md)
63
+ - [doc/CURRENT_ATTRIBUTES.md](doc/CURRENT_ATTRIBUTES.md) — per-request namespaces (Auth::Current, Accounts::Current, Teams::Current, Core::Current)
64
+ - [doc/INSERTION_POINTS.md](doc/INSERTION_POINTS.md) — marker format spec
65
+ - [doc/INSERTION_POINTS_CATALOGUE.md](doc/INSERTION_POINTS_CATALOGUE.md) — the canonical 33 markers
66
+ - [doc/WRITING_FOLLOW_UP_GENERATORS.md](doc/WRITING_FOLLOW_UP_GENERATORS.md) — write your own follow-up generator
67
+ - [doc/ADDING_AN_ENGINE.md](doc/ADDING_AN_ENGINE.md)
68
+ - [doc/REMOVING_AN_ENGINE.md](doc/REMOVING_AN_ENGINE.md)
69
+ - [doc/WRITING_AN_ADAPTER.md](doc/WRITING_AN_ADAPTER.md)
70
+ - [doc/TESTING.md](doc/TESTING.md)
71
+ - [doc/UPGRADING_FROM_WAVE_8.md](doc/UPGRADING_FROM_WAVE_8.md) — if you adopted seams pre-Wave-9
72
+
73
+ ## Why Seams instead of...
74
+
75
+ | ... | Seams gives you |
76
+ | --- | --- |
77
+ | Bullet Train | The substrate, not a starter kit. Code is in your repo, not behind a gem. |
78
+ | Jumpstart Pro | Same. Plus the boundary cops. |
79
+ | `rails plugin new --mountable` | Engines come pre-wired with events, registry, observability, boundary enforcement, CI. |
80
+ | Hand-rolled microservices | One process. No HTTP between services. Synchronous events with explicit subscribers. |
81
+
82
+ ## Status
83
+
84
+ Waves 1–9 complete: foundation, auth (with OAuth, API tokens,
85
+ GDPR-encrypted PII), notifications (with TypeRegistry,
86
+ ActionCable bell, multipart mailers), billing (official Stripe
87
+ gem, 13-handler webhook router, Lifetime Deals), teams (with
88
+ team scoping, role-based authz). Wave 9 added the `accounts`
89
+ engine and reworked the identity/account/team boundary —
90
+ `Auth::Identity` (the human), `Accounts::Account` (the tenant),
91
+ `Teams::Team` (the optional grouping) are now three peer engines
92
+ with one clear responsibility each. See
93
+ [CHANGELOG.md](CHANGELOG.md#wave-9--identity--account--team-rework-breaking)
94
+ and [doc/UPGRADING_FROM_WAVE_8.md](doc/UPGRADING_FROM_WAVE_8.md).
95
+
96
+ See [issue #5](https://github.com/Davidslv/seams/issues/5) for the live
97
+ work tracker.
98
+
99
+ Suite: RuboCop clean, brakeman + bundle-audit clean. Run
100
+ `bin/audit` before any push.
101
+
102
+ ## License
103
+
104
+ MIT — see [LICENSE](LICENSE).