@fayz-ai/db 0.13.0 → 0.14.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 (187) hide show
  1. package/canonical-schema.json +106 -23
  2. package/dist/index.cjs +4 -4
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +4 -4
  7. package/dist/index.js.map +1 -1
  8. package/dist/schema/spine.d.ts +42 -37
  9. package/dist/schema/spine.d.ts.map +1 -1
  10. package/migrations/000_baseline.sql +29667 -0
  11. package/migrations/001_the_tenant_has_apps.sql +314 -0
  12. package/migrations/002_the_spine_drops_the_vendor_and_the_dead.sql +129 -0
  13. package/migrations/003_the_role_rpcs_finish_and_the_mirrors_go.sql +135 -0
  14. package/migrations/004_the_projections_get_a_successor.sql +312 -0
  15. package/migrations/005_the_archetypes_anchor_to_the_unit.sql +90 -0
  16. package/migrations/006_the_helpers_read_the_source.sql +153 -0
  17. package/migrations/007_the_compat_machinery_leaves_with_the_tables.sql +77 -0
  18. package/migrations/008_the_switchers_see_across_accounts.sql +150 -0
  19. package/migrations/009_the_compat_aliases_nobody_adopted.sql +57 -0
  20. package/migrations/010_the_new_tenant_is_born_with_its_trade.sql +201 -0
  21. package/migrations/011_leadcontrol_joins_the_family.sql +116 -0
  22. package/migrations/012_chefcontrol_wears_its_own_mark.sql +28 -0
  23. package/migrations/013_the_workspace_switch_reaches_the_other_half.sql +156 -0
  24. package/migrations/014_the_chooser_can_read_what_it_offers.sql +91 -0
  25. package/migrations/015_the_unit_bindings_belong_to_one_workspace.sql +86 -0
  26. package/migrations/016_the_rule_stops_asking_every_row.sql +543 -0
  27. package/migrations/017_the_pin_is_checked_against_the_right_workspace.sql +139 -0
  28. package/migrations/018_the_bootstrap_says_what_you_reach.sql +114 -0
  29. package/migrations/019_distributing_one_row_stops_costing_the_table.sql +245 -0
  30. package/migrations/020_the_agenda_asks_where_someone_works.sql +81 -0
  31. package/migrations/022_the_line_says_which_document_it_belongs_to.sql +109 -0
  32. package/package.json +1 -1
  33. package/migrations/0000_legacy_quarantine.sql +0 -86
  34. package/migrations/0000b_straggler_sweep.sql +0 -37
  35. package/migrations/000_core_v1_convert.sql +0 -343
  36. package/migrations/001_core.sql +0 -372
  37. package/migrations/002_rls_user_tenant_ids.sql +0 -64
  38. package/migrations/003_invitations.sql +0 -17
  39. package/migrations/004_archetypes.sql +0 -343
  40. package/migrations/005_locations_archetype.sql +0 -18
  41. package/migrations/006_archetype_rls.sql +0 -74
  42. package/migrations/007_archetype_grants.sql +0 -4
  43. package/migrations/008_grants.sql +0 -5
  44. package/migrations/009_anon_hardening.sql +0 -19
  45. package/migrations/010_migration_ledger.sql +0 -46
  46. package/migrations/011_anon_write_revoke.sql +0 -12
  47. package/migrations/012_rename_migration_ledger.sql +0 -61
  48. package/migrations/013_sequences_rls.sql +0 -22
  49. package/migrations/014_plan_entitlements.sql +0 -28
  50. package/migrations/015_agent_guard.sql +0 -108
  51. package/migrations/016_agent_guard_actor.sql +0 -102
  52. package/migrations/017_core_addresses.sql +0 -115
  53. package/migrations/018_global_search.sql +0 -482
  54. package/migrations/019_tenant_members_person_id.sql +0 -20
  55. package/migrations/020_fayz_projects.sql +0 -63
  56. package/migrations/021_tenant_roles.sql +0 -74
  57. package/migrations/022_invite_acceptance.sql +0 -91
  58. package/migrations/023_team_visibility.sql +0 -75
  59. package/migrations/024_analytics_engine.sql +0 -317
  60. package/migrations/025_created_by.sql +0 -75
  61. package/migrations/026_audit_trail.sql +0 -73
  62. package/migrations/027_domain_events.sql +0 -266
  63. package/migrations/028_tenant_scoped_token.sql +0 -127
  64. package/migrations/029_connections.sql +0 -186
  65. package/migrations/030_effect_idempotency.sql +0 -159
  66. package/migrations/031_sync_run_message.sql +0 -39
  67. package/migrations/032_connection_secrets.sql +0 -227
  68. package/migrations/033_sync_schedule.sql +0 -651
  69. package/migrations/034_custom_fields.sql +0 -55
  70. package/migrations/035_field_registry.sql +0 -148
  71. package/migrations/036_analytics_run_batch.sql +0 -84
  72. package/migrations/037_sync_tick_one_at_a_time.sql +0 -256
  73. package/migrations/038_onboarding_responses.sql +0 -103
  74. package/migrations/039_unit_tree.sql +0 -270
  75. package/migrations/040_resource_grants.sql +0 -474
  76. package/migrations/041_scoped_columns.sql +0 -192
  77. package/migrations/042_unit_scope_policies.sql +0 -145
  78. package/migrations/043_view_invoker.sql +0 -90
  79. package/migrations/044_unit_member_facts.sql +0 -47
  80. package/migrations/045_unit_entry.sql +0 -236
  81. package/migrations/046_membership_visible_to_members.sql +0 -85
  82. package/migrations/047_tasks.sql +0 -266
  83. package/migrations/048_every_login_is_a_person.sql +0 -190
  84. package/migrations/049_bookable_people.sql +0 -126
  85. package/migrations/050_authz_core.sql +0 -230
  86. package/migrations/051_authz_helpers.sql +0 -330
  87. package/migrations/052_authz_fanout.sql +0 -253
  88. package/migrations/053_authz_catalog_templates.sql +0 -402
  89. package/migrations/060_tenancy_seam.sql +0 -132
  90. package/migrations/061_create_tenant.sql +0 -125
  91. package/migrations/062_invitations.sql +0 -329
  92. package/migrations/063_legacy_tenancy_retired.sql +0 -568
  93. package/migrations/064_agent_guard_authz.sql +0 -118
  94. package/migrations/064b_supersede_unit_scope.sql +0 -205
  95. package/migrations/065_scaffold_sweep.sql +0 -139
  96. package/migrations/066_shadow_report.sql +0 -122
  97. package/migrations/070_permission_catalog.sql +0 -205
  98. package/migrations/071_v1_permission_map.sql +0 -266
  99. package/migrations/072_role_rpcs.sql +0 -126
  100. package/migrations/073_legacy_rbac_retire.sql +0 -471
  101. package/migrations/075_company_legal_entities.sql +0 -169
  102. package/migrations/076_tenant_settings.sql +0 -251
  103. package/migrations/080_people_roles.sql +0 -269
  104. package/migrations/081_people_identity.sql +0 -271
  105. package/migrations/082_people_membership_link.sql +0 -142
  106. package/migrations/083_people_data_migration.sql +0 -75
  107. package/migrations/084_people_registrations_tokens.sql +0 -282
  108. package/migrations/085_catalog_products.sql +0 -333
  109. package/migrations/086_catalog_pricing.sql +0 -194
  110. package/migrations/087_catalog_packages.sql +0 -134
  111. package/migrations/090_orders_venda.sql +0 -166
  112. package/migrations/091_orders_scaffold.sql +0 -92
  113. package/migrations/095_config_field_rules.sql +0 -261
  114. package/migrations/096_audit_append_only.sql +0 -256
  115. package/migrations/097_sequences_authorized.sql +0 -111
  116. package/migrations/098_holidays.sql +0 -80
  117. package/migrations/099_access_grants.sql +0 -293
  118. package/migrations/100_migration_schema.sql +0 -217
  119. package/migrations/101_migration_allowlist.sql +0 -202
  120. package/migrations/102_migration_rpcs.sql +0 -933
  121. package/migrations/103_migration_reconcile_ponr.sql +0 -132
  122. package/migrations/105_policies_to_authenticated.sql +0 -71
  123. package/migrations/106_function_search_path.sql +0 -55
  124. package/migrations/107_core_table_prefix.sql +0 -361
  125. package/migrations/108_authz_write_guards.sql +0 -149
  126. package/migrations/109_catalog_migration_promoted_columns.sql +0 -126
  127. package/migrations/110_people_kind_vocabulary.sql +0 -120
  128. package/migrations/111_migration_excluded_is_a_decision.sql +0 -259
  129. package/migrations/111_replacing_a_view_keeps_its_dependents.sql +0 -132
  130. package/migrations/112_money_precision_standard.sql +0 -132
  131. package/migrations/113_addresses_units_companies.sql +0 -114
  132. package/migrations/114_migrations_ledger_immutable.sql +0 -65
  133. package/migrations/115_registration_honours_field_rules.sql +0 -172
  134. package/migrations/116_field_rules_check_needs_a_tenant.sql +0 -72
  135. package/migrations/117_authz_reconciliation_schedule.sql +0 -82
  136. package/migrations/118_migration_catalog_writers.sql +0 -450
  137. package/migrations/119_migration_config_writers.sql +0 -193
  138. package/migrations/120_migration_facet_writer.sql +0 -139
  139. package/migrations/121_migration_financial_writers.sql +0 -294
  140. package/migrations/122_migration_inventory_writers.sql +0 -245
  141. package/migrations/123_migration_order_item_writer.sql +0 -144
  142. package/migrations/124_migration_ledger_writers.sql +0 -170
  143. package/migrations/125_migration_authz_people_writers.sql +0 -205
  144. package/migrations/126_owner_scoping_is_configuration.sql +0 -247
  145. package/migrations/127_scaffold_audit_hook.sql +0 -98
  146. package/migrations/128_shadow_tables_enforced.sql +0 -93
  147. package/migrations/129_order_kind_terminal_states.sql +0 -57
  148. package/migrations/130_every_login_is_a_person.sql +0 -196
  149. package/migrations/131_migration_invoice_split.sql +0 -127
  150. package/migrations/132_audit_prune_scheduled.sql +0 -28
  151. package/migrations/133_unit_is_a_session_property.sql +0 -155
  152. package/migrations/134_field_rules_on_read.sql +0 -341
  153. package/migrations/135_distribution_polarity.sql +0 -158
  154. package/migrations/136_unit_id_means_locality.sql +0 -358
  155. package/migrations/137_vendor_named_spine_objects.sql +0 -126
  156. package/migrations/138_grants_inherit_down_the_tree.sql +0 -178
  157. package/migrations/139_distributable_is_a_scaffold_option.sql +0 -109
  158. package/migrations/140_masking_is_a_scaffold_option.sql +0 -85
  159. package/migrations/141_renamed_objects_keep_a_compat_name.sql +0 -192
  160. package/migrations/142_a_person_has_addresses.sql +0 -212
  161. package/migrations/143_a_professional_has_a_rate.sql +0 -75
  162. package/migrations/144_a_product_can_be_sold_in_sizes.sql +0 -57
  163. package/migrations/145_the_app_says_which_tenant_it_is_in.sql +0 -123
  164. package/migrations/146_products_stock_has_one_writer.sql +0 -67
  165. package/migrations/147_every_archetype_has_a_kind_registry.sql +0 -388
  166. package/migrations/148_the_legacy_archetype_stops_being_writable.sql +0 -154
  167. package/migrations/149_the_event_log_gets_a_consumer.sql +0 -331
  168. package/migrations/150_the_app_is_configured_in_the_database.sql +0 -285
  169. package/migrations/151_stock_balance_is_an_archetype.sql +0 -144
  170. package/migrations/152_a_file_is_an_archetype.sql +0 -222
  171. package/migrations/153_a_plugin_calls_a_service_through_one_door.sql +0 -199
  172. package/migrations/154_the_plan_is_a_ceiling.sql +0 -258
  173. package/migrations/155_a_tenant_can_leave.sql +0 -271
  174. package/migrations/156_the_service_door_has_a_server_side.sql +0 -335
  175. package/migrations/157_nobody_creates_objects_in_public.sql +0 -74
  176. package/migrations/158_the_registry_owns_the_status_vocabulary.sql +0 -153
  177. package/migrations/159_the_plan_catalogue_gets_its_first_rows.sql +0 -132
  178. package/migrations/160_the_vertical_decides_what_starts_on.sql +0 -246
  179. package/migrations/161_a_tenant_leaves_with_its_data.sql +0 -363
  180. package/migrations/162_every_name_has_one_creator_for_real.sql +0 -126
  181. package/migrations/163_a_species_nobody_declared_goes_to_quarantine.sql +0 -184
  182. package/migrations/164_the_sequence_table_joins_the_register.sql +0 -26
  183. package/migrations/165_a_view_is_not_a_way_in.sql +0 -90
  184. package/migrations/166_the_platform_billing_leftovers_go.sql +0 -72
  185. package/migrations/167_a_view_gets_back_what_its_table_grants.sql +0 -112
  186. package/migrations/168_the_grant_census_stops_crying_wolf.sql +0 -33
  187. package/migrations/169_the_census_asks_postgres_instead_of_guessing.sql +0 -45
@@ -1,205 +0,0 @@
1
- -- ============================================================================
2
- -- 070_permission_catalog.sql — the RBAC catalog seeded from declaredFeatures (#136).
3
- --
4
- -- GENERATED by scripts/emit-permission-catalog.mjs — do not edit by hand.
5
- -- regenerate: pnpm emit:permission-catalog
6
- -- verify: pnpm check:permission-catalog (CI: fails when out of date)
7
- -- Once this file is recorded in a real database's ledger it is frozen: regenerate
8
- -- into a NEW numbered file (--out …/0NN_permission_catalog_vK.sql), never here.
9
- --
10
- -- One key per {feature}.{action}; app.seed_permissions upserts and never removes
11
- -- (removing a key is a decision, not a build). New keys reach every tenant's
12
- -- system owner role through the permissions_grant_owner trigger (043).
13
- --
14
- -- Sources (plugin id ← manifest: features; [c] = conditional on config, [r] = referenced only):
15
- -- admin ← plugins/plugin-admin/src/index.ts: admin
16
- -- agenda ← plugins/plugin-agenda/src/index.ts: agenda.schedules, appointments
17
- -- automations ← plugins/plugin-automations/src/index.ts: automations
18
- -- blog ← plugins/plugin-blog/src/index.ts: blog
19
- -- conversations ← plugins/plugin-conversations/src/index.ts: conversations
20
- -- courses ← plugins/plugin-courses/src/index.ts: courses, courses.finance, courses.sales
21
- -- crm ← plugins/plugin-crm/src/index.ts: crm.leads, crm.pipeline, crm.quotes, sales
22
- -- dashboard ← plugins/plugin-dashboard/src/index.ts: dashboard
23
- -- financial ← plugins/plugin-financial/src/index.ts: financial, financial.commissions[c], financial.payables[c], financial.receivables[c]
24
- -- custom_forms ← plugins/plugin-forms/src/index.ts: custom_forms
25
- -- inventory ← plugins/plugin-inventory/src/index.ts: inventory, inventory.recipes[c]
26
- -- marketing ← plugins/plugin-marketing/src/index.ts: marketing, marketing.blog[c], marketing.content[c], marketing.landing-pages[c]
27
- -- menu ← plugins/plugin-menu/src/index.ts: menu[r]
28
- -- orders ← plugins/plugin-orders/src/index.ts: orders[r]
29
- -- reports ← plugins/plugin-reports/src/index.ts: reports
30
- -- reputation ← plugins/plugin-reputation/src/index.ts: reputation
31
- -- scribe ← plugins/plugin-scribe/src/index.ts: scribe{read,create,edit,delete}
32
- -- shop ← plugins/plugin-shop/src/index.ts: shop[r]
33
- -- sites ← plugins/plugin-sites/src/index.ts: sites
34
- -- tables ← plugins/plugin-tables/src/index.ts: tables[r]
35
- -- ============================================================================
36
-
37
- SELECT app.seed_permissions('[
38
- {"key":"admin.create","plugin":"admin"},
39
- {"key":"admin.delete","plugin":"admin"},
40
- {"key":"admin.edit","plugin":"admin"},
41
- {"key":"admin.manage","plugin":"admin"},
42
- {"key":"admin.read","plugin":"admin"},
43
- {"key":"agenda.schedules.create","plugin":"agenda","description":"Schedule Management: create"},
44
- {"key":"agenda.schedules.delete","plugin":"agenda","description":"Schedule Management: delete"},
45
- {"key":"agenda.schedules.edit","plugin":"agenda","description":"Schedule Management: edit"},
46
- {"key":"agenda.schedules.manage","plugin":"agenda","description":"Schedule Management: manage"},
47
- {"key":"agenda.schedules.read","plugin":"agenda","description":"Schedule Management: read"},
48
- {"key":"appointments.create","plugin":"agenda"},
49
- {"key":"appointments.delete","plugin":"agenda"},
50
- {"key":"appointments.edit","plugin":"agenda"},
51
- {"key":"appointments.manage","plugin":"agenda"},
52
- {"key":"appointments.read","plugin":"agenda"},
53
- {"key":"automations.create","plugin":"automations","description":"Automations: create"},
54
- {"key":"automations.delete","plugin":"automations","description":"Automations: delete"},
55
- {"key":"automations.edit","plugin":"automations","description":"Automations: edit"},
56
- {"key":"automations.manage","plugin":"automations","description":"Automations: manage"},
57
- {"key":"automations.read","plugin":"automations","description":"Automations: read"},
58
- {"key":"blog.create","plugin":"blog","description":"Blog: create"},
59
- {"key":"blog.delete","plugin":"blog","description":"Blog: delete"},
60
- {"key":"blog.edit","plugin":"blog","description":"Blog: edit"},
61
- {"key":"blog.manage","plugin":"blog","description":"Blog: manage"},
62
- {"key":"blog.read","plugin":"blog","description":"Blog: read"},
63
- {"key":"conversations.create","plugin":"conversations","description":"Conversations: create"},
64
- {"key":"conversations.delete","plugin":"conversations","description":"Conversations: delete"},
65
- {"key":"conversations.edit","plugin":"conversations","description":"Conversations: edit"},
66
- {"key":"conversations.manage","plugin":"conversations","description":"Conversations: manage"},
67
- {"key":"conversations.read","plugin":"conversations","description":"Conversations: read"},
68
- {"key":"courses.create","plugin":"courses","description":"Courses: create"},
69
- {"key":"courses.delete","plugin":"courses","description":"Courses: delete"},
70
- {"key":"courses.edit","plugin":"courses","description":"Courses: edit"},
71
- {"key":"courses.finance.create","plugin":"courses","description":"Financial: create"},
72
- {"key":"courses.finance.delete","plugin":"courses","description":"Financial: delete"},
73
- {"key":"courses.finance.edit","plugin":"courses","description":"Financial: edit"},
74
- {"key":"courses.finance.manage","plugin":"courses","description":"Financial: manage"},
75
- {"key":"courses.finance.read","plugin":"courses","description":"Financial: read"},
76
- {"key":"courses.manage","plugin":"courses","description":"Courses: manage"},
77
- {"key":"courses.read","plugin":"courses","description":"Courses: read"},
78
- {"key":"courses.sales.create","plugin":"courses","description":"Sales: create"},
79
- {"key":"courses.sales.delete","plugin":"courses","description":"Sales: delete"},
80
- {"key":"courses.sales.edit","plugin":"courses","description":"Sales: edit"},
81
- {"key":"courses.sales.manage","plugin":"courses","description":"Sales: manage"},
82
- {"key":"courses.sales.read","plugin":"courses","description":"Sales: read"},
83
- {"key":"crm.leads.create","plugin":"crm"},
84
- {"key":"crm.leads.delete","plugin":"crm"},
85
- {"key":"crm.leads.edit","plugin":"crm"},
86
- {"key":"crm.leads.manage","plugin":"crm"},
87
- {"key":"crm.leads.read","plugin":"crm"},
88
- {"key":"crm.pipeline.create","plugin":"crm"},
89
- {"key":"crm.pipeline.delete","plugin":"crm"},
90
- {"key":"crm.pipeline.edit","plugin":"crm"},
91
- {"key":"crm.pipeline.manage","plugin":"crm"},
92
- {"key":"crm.pipeline.read","plugin":"crm"},
93
- {"key":"crm.quotes.create","plugin":"crm"},
94
- {"key":"crm.quotes.delete","plugin":"crm"},
95
- {"key":"crm.quotes.edit","plugin":"crm"},
96
- {"key":"crm.quotes.manage","plugin":"crm"},
97
- {"key":"crm.quotes.read","plugin":"crm"},
98
- {"key":"custom_forms.create","plugin":"custom_forms"},
99
- {"key":"custom_forms.delete","plugin":"custom_forms"},
100
- {"key":"custom_forms.edit","plugin":"custom_forms"},
101
- {"key":"custom_forms.manage","plugin":"custom_forms"},
102
- {"key":"custom_forms.read","plugin":"custom_forms"},
103
- {"key":"dashboard.create","plugin":"dashboard"},
104
- {"key":"dashboard.delete","plugin":"dashboard"},
105
- {"key":"dashboard.edit","plugin":"dashboard"},
106
- {"key":"dashboard.manage","plugin":"dashboard"},
107
- {"key":"dashboard.read","plugin":"dashboard"},
108
- {"key":"financial.commissions.create","plugin":"financial"},
109
- {"key":"financial.commissions.delete","plugin":"financial"},
110
- {"key":"financial.commissions.edit","plugin":"financial"},
111
- {"key":"financial.commissions.manage","plugin":"financial"},
112
- {"key":"financial.commissions.read","plugin":"financial"},
113
- {"key":"financial.create","plugin":"financial"},
114
- {"key":"financial.delete","plugin":"financial"},
115
- {"key":"financial.edit","plugin":"financial"},
116
- {"key":"financial.manage","plugin":"financial"},
117
- {"key":"financial.payables.create","plugin":"financial"},
118
- {"key":"financial.payables.delete","plugin":"financial"},
119
- {"key":"financial.payables.edit","plugin":"financial"},
120
- {"key":"financial.payables.manage","plugin":"financial"},
121
- {"key":"financial.payables.read","plugin":"financial"},
122
- {"key":"financial.read","plugin":"financial"},
123
- {"key":"financial.read_all","plugin":"financial"},
124
- {"key":"financial.receivables.create","plugin":"financial"},
125
- {"key":"financial.receivables.delete","plugin":"financial"},
126
- {"key":"financial.receivables.edit","plugin":"financial"},
127
- {"key":"financial.receivables.manage","plugin":"financial"},
128
- {"key":"financial.receivables.read","plugin":"financial"},
129
- {"key":"inventory.create","plugin":"inventory"},
130
- {"key":"inventory.delete","plugin":"inventory"},
131
- {"key":"inventory.edit","plugin":"inventory"},
132
- {"key":"inventory.manage","plugin":"inventory"},
133
- {"key":"inventory.read","plugin":"inventory"},
134
- {"key":"inventory.recipes.create","plugin":"inventory"},
135
- {"key":"inventory.recipes.delete","plugin":"inventory"},
136
- {"key":"inventory.recipes.edit","plugin":"inventory"},
137
- {"key":"inventory.recipes.manage","plugin":"inventory"},
138
- {"key":"inventory.recipes.read","plugin":"inventory"},
139
- {"key":"marketing.blog.create","plugin":"marketing"},
140
- {"key":"marketing.blog.delete","plugin":"marketing"},
141
- {"key":"marketing.blog.edit","plugin":"marketing"},
142
- {"key":"marketing.blog.manage","plugin":"marketing"},
143
- {"key":"marketing.blog.read","plugin":"marketing"},
144
- {"key":"marketing.content.create","plugin":"marketing"},
145
- {"key":"marketing.content.delete","plugin":"marketing"},
146
- {"key":"marketing.content.edit","plugin":"marketing"},
147
- {"key":"marketing.content.manage","plugin":"marketing"},
148
- {"key":"marketing.content.read","plugin":"marketing"},
149
- {"key":"marketing.create","plugin":"marketing"},
150
- {"key":"marketing.delete","plugin":"marketing"},
151
- {"key":"marketing.edit","plugin":"marketing"},
152
- {"key":"marketing.landing-pages.create","plugin":"marketing"},
153
- {"key":"marketing.landing-pages.delete","plugin":"marketing"},
154
- {"key":"marketing.landing-pages.edit","plugin":"marketing"},
155
- {"key":"marketing.landing-pages.manage","plugin":"marketing"},
156
- {"key":"marketing.landing-pages.read","plugin":"marketing"},
157
- {"key":"marketing.manage","plugin":"marketing"},
158
- {"key":"marketing.read","plugin":"marketing"},
159
- {"key":"menu.create","plugin":"menu"},
160
- {"key":"menu.delete","plugin":"menu"},
161
- {"key":"menu.edit","plugin":"menu"},
162
- {"key":"menu.manage","plugin":"menu"},
163
- {"key":"menu.read","plugin":"menu"},
164
- {"key":"orders.create","plugin":"orders"},
165
- {"key":"orders.delete","plugin":"orders"},
166
- {"key":"orders.edit","plugin":"orders"},
167
- {"key":"orders.manage","plugin":"orders"},
168
- {"key":"orders.read","plugin":"orders"},
169
- {"key":"orders.read_all","plugin":"orders"},
170
- {"key":"reports.create","plugin":"reports"},
171
- {"key":"reports.delete","plugin":"reports"},
172
- {"key":"reports.edit","plugin":"reports"},
173
- {"key":"reports.manage","plugin":"reports"},
174
- {"key":"reports.read","plugin":"reports"},
175
- {"key":"reputation.create","plugin":"reputation","description":"Reputation: create"},
176
- {"key":"reputation.delete","plugin":"reputation","description":"Reputation: delete"},
177
- {"key":"reputation.edit","plugin":"reputation","description":"Reputation: edit"},
178
- {"key":"reputation.manage","plugin":"reputation","description":"Reputation: manage"},
179
- {"key":"reputation.read","plugin":"reputation","description":"Reputation: read"},
180
- {"key":"sales.create","plugin":"crm"},
181
- {"key":"sales.delete","plugin":"crm"},
182
- {"key":"sales.edit","plugin":"crm"},
183
- {"key":"sales.manage","plugin":"crm"},
184
- {"key":"sales.read","plugin":"crm"},
185
- {"key":"scribe.create","plugin":"scribe"},
186
- {"key":"scribe.delete","plugin":"scribe"},
187
- {"key":"scribe.edit","plugin":"scribe"},
188
- {"key":"scribe.manage","plugin":"scribe"},
189
- {"key":"scribe.read","plugin":"scribe"},
190
- {"key":"shop.create","plugin":"shop"},
191
- {"key":"shop.delete","plugin":"shop"},
192
- {"key":"shop.edit","plugin":"shop"},
193
- {"key":"shop.manage","plugin":"shop"},
194
- {"key":"shop.read","plugin":"shop"},
195
- {"key":"sites.create","plugin":"sites","description":"Sites & Funnels: create"},
196
- {"key":"sites.delete","plugin":"sites","description":"Sites & Funnels: delete"},
197
- {"key":"sites.edit","plugin":"sites","description":"Sites & Funnels: edit"},
198
- {"key":"sites.manage","plugin":"sites","description":"Sites & Funnels: manage"},
199
- {"key":"sites.read","plugin":"sites","description":"Sites & Funnels: read"},
200
- {"key":"tables.create","plugin":"tables"},
201
- {"key":"tables.delete","plugin":"tables"},
202
- {"key":"tables.edit","plugin":"tables"},
203
- {"key":"tables.manage","plugin":"tables"},
204
- {"key":"tables.read","plugin":"tables"}
205
- ]'::jsonb);
@@ -1,266 +0,0 @@
1
- -- ============================================================================
2
- -- 071_v1_permission_map.sql — the V1 → V2 permission mapping as data (#136).
3
- --
4
- -- V1 (the-chef / beautyplace) had one catalog of snake_case codes × four flags
5
- -- (can_view / can_insert / can_edit / can_delete) per "regra de permissão", an
6
- -- admin/master/owner bypass in code and a per-tenant enforcement flag. V2 has
7
- -- '{plugin}.{action}' keys, roles per tenant and RLS as the only law.
8
- --
9
- -- The mapping was produced by reading the V1 REPO (src/**, supabase/functions/**,
10
- -- supabase/migrations/**; never a data dump): every code seeded by a migration
11
- -- plus every code the code enforces, each decided as
12
- -- mapped → a V2 feature (the four flags expand to read/create/edit/delete)
13
- -- or one V2 key (any flag grants it), plus optional extra keys
14
- -- backlog → V2 has no surface for it yet: nothing is granted, nothing is lost
15
- -- in a way anyone can act on today (listed for the roadmap)
16
- -- dropped → superseded/inactive in V1, or a bypass/flag V2 refuses to carry
17
- -- The prose (why each row) is docs/data/phase-0/01b-v1-permission-mapping.md;
18
- -- this table is what the extractor/ledger slice reads. Rows only, no client data.
19
- --
20
- -- app.v1_permission_keys(code, view, insert, edit, delete) is the one function
21
- -- that turns a V1 rule detail into the V2 keys to grant — the extractor calls
22
- -- it instead of re-implementing the expansion.
23
- -- ============================================================================
24
-
25
- CREATE TABLE IF NOT EXISTS app.v1_permission_map (
26
- v1_code text PRIMARY KEY,
27
- v1_category text,
28
- v1_name text,
29
- seeded_in_repo boolean NOT NULL DEFAULT true, -- inserted by a V1 migration (false ⇒ exists only in the live table)
30
- active_in_v1 boolean, -- catalog `active` at the head of the V1 migrations (null when not seeded)
31
- enforced_in_v1 boolean NOT NULL DEFAULT false, -- appears at an enforcement point (can()/usePermission/<Can>/permissionCode/user_has_permission)
32
- status text NOT NULL CHECK (status IN ('mapped', 'backlog', 'dropped')),
33
- kind text CHECK (kind IN ('feature', 'key')),
34
- v2_feature text, -- kind='feature': view→.read, insert→.create, edit→.edit, delete→.delete (fallback .manage)
35
- v2_key text REFERENCES app.permissions(key) ON DELETE SET NULL, -- kind='key': the key any true flag grants; kind='feature': the .read key
36
- v2_extra_keys text[] NOT NULL DEFAULT '{}', -- granted alongside whenever any flag is true
37
- note text,
38
- updated_at timestamptz NOT NULL DEFAULT now(),
39
- CHECK (status <> 'mapped' OR (kind IS NOT NULL AND v2_key IS NOT NULL)),
40
- CHECK (kind IS DISTINCT FROM 'feature' OR v2_feature IS NOT NULL),
41
- CHECK (v1_code ~ '^[a-z][a-z0-9_]*$')
42
- );
43
- ALTER TABLE app.v1_permission_map ENABLE ROW LEVEL SECURITY;
44
- GRANT SELECT ON app.v1_permission_map TO authenticated, service_role;
45
- GRANT ALL ON app.v1_permission_map TO service_role;
46
- DROP POLICY IF EXISTS v1_permission_map_select ON app.v1_permission_map;
47
- CREATE POLICY v1_permission_map_select ON app.v1_permission_map FOR SELECT TO authenticated USING (true);
48
- COMMENT ON TABLE app.v1_permission_map IS
49
- 'V1 permission code → V2 permission key mapping (#136). Read by the V1 extractor; prose in docs/data/phase-0/01b-v1-permission-mapping.md.';
50
-
51
- -- ── the rows ────────────────────────────────────────────────────────────
52
- -- Upsert on v1_code so a later file may refine a row (status/target/note)
53
- -- without editing this one; nothing here deletes.
54
- INSERT INTO app.v1_permission_map
55
- (v1_code, v1_category, v1_name, seeded_in_repo, active_in_v1, enforced_in_v1, status, kind, v2_feature, v2_key, v2_extra_keys, note)
56
- VALUES
57
- ('agenda_calendar', 'Agenda', 'Tela de Agendamento', true, true, true, 'mapped', 'feature', 'agenda', 'agenda.read', '{}'::text[], 'The agenda screen. RLS on public.appointments/schedules is keyed on agenda.* (043); plugin-agenda still gates its UI on appointments.* — see the divergence note.'),
58
- ('agenda_confirmation', 'Agenda', 'Confirmação de Agendamentos', true, true, true, 'mapped', 'feature', 'agenda', 'agenda.read', '{}'::text[], 'Sub-screen of the agenda (WhatsApp confirmations); coarser: V2 has no finer key yet.'),
59
- ('checkin_dashboard', 'Agenda', 'Check-in de Clientes', true, true, true, 'mapped', 'feature', 'agenda', 'agenda.read', '{}'::text[], 'Client check-in is an agenda flow (PRD 07 FieldRules check-in); coarser.'),
60
- ('agenda_reservations', 'Agenda', 'Reservas', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Table/slot reservations — plugin-tables (`tables.*`) once it declares features.'),
61
- ('agenda_schedules', 'Agenda', 'Escalas', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced in V1. Natural target: agenda.schedules.* (plugin-agenda declares it).'),
62
- ('appointments_confirm', 'Agenda', 'Confirmação de Agendamentos', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Inactive since the 2026-05-12 reseed; superseded by agenda_confirmation.'),
63
- ('appointments_schedule', 'Agenda', 'Tela de Agendamento', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Inactive since the 2026-05-12 reseed; superseded by agenda_calendar.'),
64
- ('clients_list', 'Clientes', 'Listar Clientes', true, true, true, 'mapped', 'feature', 'people', 'people.read', '{}'::text[], 'The client list: view/insert/edit/delete map 1:1 to people.read/create/edit/delete.'),
65
- ('clients_create', 'Clientes', 'Cadastrar Cliente', true, true, true, 'mapped', 'key', NULL, 'people.create', '{}'::text[], 'The "new client" screen; any granted flag becomes people.create.'),
66
- ('clients_card', 'Clientes', 'Ficha do Cliente', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: people.read (+ people.read_all for the full record of others’ clients).'),
67
- ('clients_manage', 'Clientes', 'Gerenciar Clientes', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Inactive since the 2026-05-12 reseed; superseded by clients_list/clients_create.'),
68
- ('communication_dashboard', 'Comunicação', 'Comunicação', true, true, true, 'mapped', 'feature', 'automations', 'automations.read', '{}'::text[], 'V1 "Comunicação" (WhatsApp templates, triggers, dispatch log) is plugin-automations in V2 (messaging moved under Automações); coarser.'),
69
- ('communication_manual_confirmation', 'Comunicação', 'Confirmação Manual (Mensagem)', true, true, true, 'mapped', 'feature', 'automations', 'automations.read', '{}'::text[], 'Manual confirmation message config; coarser (automations.*).'),
70
- ('communication_dispatch_log', 'Comunicação', 'Log de Disparos', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: automations.read.'),
71
- ('communication_events', 'Comunicação', 'Eventos / Gatilhos', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: automations.manage.'),
72
- ('communication_templates', 'Comunicação', 'Templates de Mensagem', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: automations.manage.'),
73
- ('communication_whatsapp', 'Comunicação', 'WhatsApp Config', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: conversations.manage / settings.manage.'),
74
- ('config_communication', 'Configurações', 'Comunicação', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Inactive since the 2026-05-12 reseed.'),
75
- ('config_hub', 'Configurações', 'Hub de Configurações', true, true, true, 'mapped', 'feature', 'settings', 'settings.read', '{}'::text[], 'The settings hub: view→settings.read, edit→settings.manage.'),
76
- ('config_appearance', NULL, NULL, false, NULL, true, 'mapped', 'feature', 'settings', 'settings.read', '{}'::text[], 'Branding (logo/name) — tenant settings (PRD 02 R5). Not seeded by any migration in the V1 repo (exists only in the live table).'),
77
- ('config_company', 'Configurações', 'Empresa', true, true, true, 'mapped', 'feature', 'units', 'units.read', '{}'::text[], 'Empresa = the legal entity a unit references (PRD 02 R2, #138): units.read/units.manage.'),
78
- ('config_company_type', 'Configurações', 'Tipo de Empresa', true, true, true, 'mapped', 'feature', 'tenant', 'tenant.read', '{}'::text[], 'Franchise mode → tenants.kind (ADR 0002): tenant.read/tenant.manage.'),
79
- ('config_cancellation_rules', 'Configurações', 'Regras de Cancelamento', true, true, true, 'mapped', 'feature', 'agenda', 'agenda.read', '{}'::text[], 'Appointment cancellation policy — agenda settings; coarser.'),
80
- ('config_holidays', 'Configurações', 'Feriados', true, true, true, 'mapped', 'feature', 'agenda', 'agenda.read', '{}'::text[], 'Holidays feed the agenda availability; coarser.'),
81
- ('config_chart_accounts', 'Configurações', 'Plano de Contas', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'plg_financial_chart_of_accounts is financial data: financial.read/manage.'),
82
- ('config_cost_centers', 'Configurações', 'Centros de Custo', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'plg_financial_cost_centers: financial.read/manage.'),
83
- ('config_payment_methods', 'Configurações', 'Formas de Recebimento', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'plg_financial_payment_methods: financial.read/manage.'),
84
- ('config_commission_rules', 'Configurações', 'Regras de Comissão', true, true, true, 'mapped', 'feature', 'financial.commissions', 'financial.commissions.read', '{}'::text[], 'Commission rules live with commissions.'),
85
- ('config_discount_rules', 'Configurações', 'Regras de Desconto', true, true, true, 'mapped', 'feature', 'orders', 'orders.read', '{}'::text[], 'Discount rules apply to orders/bills; coarser.'),
86
- ('config_cover_charge', 'Configurações', 'Taxas de Ingresso', true, true, true, 'mapped', 'feature', 'orders', 'orders.read', '{}'::text[], 'Cover charge is an order fee (chef); coarser.'),
87
- ('config_service_charge', 'Configurações', 'Taxa de Serviço', true, true, true, 'mapped', 'feature', 'orders', 'orders.read', '{}'::text[], 'Service charge is an order fee (chef); coarser.'),
88
- ('config_price_tables', 'Configurações', 'Tabelas de Preço', true, true, true, 'mapped', 'feature', 'catalog', 'catalog.read', '{}'::text[], 'Price tables are catalog pricing (PRD 04).'),
89
- ('config_price_variations', 'Configurações', 'Variações de Preço', true, true, true, 'mapped', 'feature', 'catalog', 'catalog.read', '{}'::text[], 'Price variations are catalog pricing (PRD 04).'),
90
- ('config_field_visibility', 'Configurações', 'Ocultação de Dados', true, true, true, 'mapped', 'feature', 'settings', 'settings.read', '{}'::text[], 'FieldRules (PRD 07): tenant configuration → settings.*.'),
91
- ('config_required_fields', 'Configurações', 'Campos Obrigatórios', true, true, true, 'mapped', 'feature', 'settings', 'settings.read', '{}'::text[], 'FieldRules (PRD 07): tenant configuration → settings.*.'),
92
- ('config_forms', 'Configurações', 'Formulários', true, true, true, 'mapped', 'feature', 'custom_forms', 'custom_forms.read', '{}'::text[], 'plugin-forms (custom_forms.*).'),
93
- ('config_permission_rules', 'Configurações', 'Regras de Permissão', true, true, true, 'mapped', 'feature', 'roles', 'roles.read', '{}'::text[], 'The permission-rules screen becomes the roles editor: roles.read/roles.manage.'),
94
- ('config_contracts', 'Configurações', 'Modelos de Contratos', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Contract templates: no V2 surface (plugin-crm has leads/quotes/pipeline, no contracts).'),
95
- ('config_qr_access', 'Configurações', 'Acesso por QR Code', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced; QR-code unit access has no V2 surface.'),
96
- ('config_software_profile', 'Configurações', 'Perfil de Software', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced; software profiles become tenant plugin configuration (PRD 02 R3), not a permission.'),
97
- ('crm_dashboard', 'Marketing', 'CRM', true, true, true, 'mapped', 'feature', 'sales', 'sales.read', '{}'::text[], 'plugin-crm’s main feature id is `sales`.'),
98
- ('marketing_dashboard', 'Marketing', 'Marketing', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: marketing.read.'),
99
- ('marketing_online_booking', 'Marketing', 'Agendamento Online', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Public booking config → agenda settings.'),
100
- ('dashboard_alerts', 'Dashboard', 'Alertas e Destaques', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Operational widget → dashboard.read.'),
101
- ('dashboard_appointments_status', 'Dashboard', 'Status dos Agendamentos', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Operational widget (V1 also inferred it from agenda_calendar).'),
102
- ('dashboard_kpi_operational', 'Dashboard', 'KPIs Operacionais', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Operational widget (V1 also inferred it from agenda_calendar).'),
103
- ('dashboard_top_services', 'Dashboard', 'Top Serviços', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Operational widget.'),
104
- ('dashboard_units_ranking', 'Dashboard', 'Ranking de Unidades', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Operational widget (unit scope comes from user_unit_access, not from a permission).'),
105
- ('dashboard_weekly_trend', 'Dashboard', 'Desempenho 7 Dias', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Operational widget.'),
106
- ('dashboard_monthly_trend', 'Dashboard', 'Tendência Mensal', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Operational widget.'),
107
- ('dashboard_goals', 'Dashboard', 'Metas de Vendas', true, true, true, 'mapped', 'feature', 'dashboard', 'dashboard.read', '{}'::text[], 'Sales goals widget.'),
108
- ('dashboard_kpi_consolidated', 'Dashboard', 'KPIs Consolidados', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'Money widget: V1 never let it inherit from the agenda; V2 gates money on financial.read.'),
109
- ('dashboard_payables', 'Dashboard', 'Contas a Pagar (Dashboard)', true, true, true, 'mapped', 'feature', 'financial.payables', 'financial.payables.read', '{}'::text[], 'Money widget → financial.payables.read.'),
110
- ('dashboard_receivables', 'Dashboard', 'Contas a Receber (Dashboard)', true, true, true, 'mapped', 'feature', 'financial.receivables', 'financial.receivables.read', '{}'::text[], 'Money widget → financial.receivables.read.'),
111
- ('dashboard_stock_critical', 'Dashboard', 'Estoque Crítico', true, true, true, 'mapped', 'feature', 'inventory', 'inventory.read', '{}'::text[], 'Stock widget → inventory.read.'),
112
- ('dashboard_revenue_by_service', 'Dashboard', 'Receita por Serviço', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: financial.read.'),
113
- ('financial_dashboard', 'Financeiro', 'Financeiro (Painel)', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'The financial panel.'),
114
- ('financial_payable', 'Financeiro', 'Contas a Pagar', true, true, true, 'mapped', 'feature', 'financial.payables', 'financial.payables.read', '{}'::text[], 'Contas a pagar.'),
115
- ('financial_receivable', 'Financeiro', 'Contas a Receber', true, true, true, 'mapped', 'feature', 'financial.receivables', 'financial.receivables.read', '{}'::text[], 'Contas a receber.'),
116
- ('financial_cash', 'Financeiro', 'Caixas', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', ARRAY['financial.read_all']::text[], 'Managerial view of every cash register of the units: financial.* plus read_all (sessions are owner-scoped rows).'),
117
- ('financial_cash_receipt', 'Financeiro', 'Receber pelo Caixinha', true, true, true, 'mapped', 'key', NULL, 'financial.cash_session', ARRAY['financial.create']::text[], 'Receive through the caixinha: open/operate a session + create movements.'),
118
- ('financial_cash_payment', 'Financeiro', 'Pagar pelo Caixinha', true, true, true, 'mapped', 'key', NULL, 'financial.cash_session', ARRAY['financial.create']::text[], 'Pay through the caixinha: open/operate a session + create movements.'),
119
- ('financial_cash_review', 'Financeiro', 'Conferência de Caixa', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', ARRAY['financial.read_all']::text[], 'Review/approve closings of other users’ sessions: read_all + edit.'),
120
- ('financial_cash_own', 'Financeiro', 'Caixa Próprio', true, false, true, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Deactivated by 20260803150000 (superseded by financial_cash_receipt/payment); still named in one V1 RPC.'),
121
- ('financial_bank_statement', 'Financeiro', 'Extrato Bancário', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'Bank accounts and statements.'),
122
- ('financial_reconciliation', NULL, NULL, false, NULL, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'Bank reconciliation. Not seeded by any migration in the V1 repo. plugin-banking-br (openbanking) declares no feature yet; financial.* is the coarser home.'),
123
- ('financial_recurring_bills', NULL, NULL, false, NULL, true, 'mapped', 'feature', 'financial.payables', 'financial.payables.read', '{}'::text[], 'Recurring bills are payables. Not seeded by any migration in the V1 repo.'),
124
- ('financial_ai_expense', NULL, NULL, false, NULL, true, 'mapped', 'feature', 'financial.payables', 'financial.payables.read', '{}'::text[], 'AI expense extraction creates payables. Not seeded by any migration in the V1 repo.'),
125
- ('financial_commissions', 'Financeiro', 'Comissões', true, true, true, 'mapped', 'feature', 'financial.commissions', 'financial.commissions.read', '{}'::text[], 'Commissions.'),
126
- ('financial_credit_card', 'Financeiro', 'Cartões de Crédito', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'Card brands / card fees (plg_financial_card_brands).'),
127
- ('financial_payment', 'Financeiro', 'Pagamento (geral)', true, true, true, 'mapped', 'key', NULL, 'financial.payables.edit', '{}'::text[], 'Settle a payable without a cash session (settlement gate).'),
128
- ('financial_receipt', 'Financeiro', 'Recebimento (geral)', true, true, true, 'mapped', 'key', NULL, 'financial.receivables.edit', '{}'::text[], 'Settle a receivable without a cash session (settlement gate).'),
129
- ('financial_payment_unlink', 'Financeiro', 'Desvincular pagamento de parcela', true, true, true, 'mapped', 'key', NULL, 'financial.edit', '{}'::text[], 'Unlink a payment from an installment; V2 has no finer key — coarser.'),
130
- ('financial_gift_cards', 'Financeiro', 'Gift Cards', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Gift cards have no V2 surface.'),
131
- ('financial_reports', 'Financeiro', 'Extratos e Relatórios', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Inactive since the 2026-05-12 reseed; reports_* superseded it.'),
132
- ('financial_free_transaction', 'Financeiro', 'Transacionar sem Caixa', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Deactivated by 20260803150000 (superseded by financial_payment/receipt).'),
133
- ('inventory_dashboard', 'Estoque', 'Estoque (Painel)', true, true, true, 'mapped', 'feature', 'inventory', 'inventory.read', '{}'::text[], 'The stock panel.'),
134
- ('inventory_movements', 'Estoque', 'Movimentações', true, true, true, 'mapped', 'feature', 'inventory', 'inventory.read', '{}'::text[], 'Stock movements (plg_inventory_stock_movements).'),
135
- ('inventory_products', 'Estoque', 'Produtos', true, true, true, 'mapped', 'feature', 'catalog', 'catalog.read', '{}'::text[], 'Products are catalog items in V2 (public.products, PRD 04).'),
136
- ('inventory_categories', NULL, NULL, false, NULL, true, 'mapped', 'feature', 'inventory', 'inventory.read', '{}'::text[], 'plg_inventory_product_categories. Not seeded by any migration in the V1 repo.'),
137
- ('inventory_recipes', NULL, NULL, false, NULL, true, 'mapped', 'feature', 'inventory.recipes', 'inventory.recipes.read', '{}'::text[], 'plugin-inventory declares inventory.recipes when the module is on. Not seeded by any migration in the V1 repo.'),
138
- ('inventory_stock_locations', NULL, NULL, false, NULL, true, 'mapped', 'feature', 'inventory', 'inventory.read', '{}'::text[], 'plg_inventory_stock_locations. Not seeded by any migration in the V1 repo.'),
139
- ('inventory_danfe', 'Estoque', 'Importação DANFE', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced; DANFE import has no V2 key (plg_financial_nfe exists without a permission).'),
140
- ('fiscal_dashboard', NULL, NULL, false, NULL, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (InventorySidebar) but no V2 fiscal surface yet; not seeded by any migration in the V1 repo.'),
141
- ('fiscal_dfe_inbox', NULL, NULL, false, NULL, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'No V2 fiscal surface; not seeded by any migration in the V1 repo.'),
142
- ('fiscal_dfe_manifest', NULL, NULL, false, NULL, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'No V2 fiscal surface; not seeded by any migration in the V1 repo.'),
143
- ('fiscal_danfe_import', NULL, NULL, false, NULL, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'No V2 fiscal surface; not seeded by any migration in the V1 repo.'),
144
- ('fiscal_groups', NULL, NULL, false, NULL, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'No V2 fiscal surface; not seeded by any migration in the V1 repo.'),
145
- ('production_dashboard', 'Produção', 'Produção (Painel)', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (InventorySidebar) but V2 has no production plugin.'),
146
- ('production_orders', 'Produção', 'Ordens de Produção', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced (only mentioned); no V2 production plugin.'),
147
- ('production_execution', 'Produção', 'Execução (estação)', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced; no V2 production plugin.'),
148
- ('production_planning', 'Produção', 'Planejamento e MRP', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced; no V2 production plugin.'),
149
- ('production_traceability', 'Produção', 'Lotes e Rastreabilidade', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced; no V2 production plugin.'),
150
- ('operations_dashboard', 'Operação', 'Operação', true, true, true, 'mapped', 'feature', 'orders', 'orders.read', '{}'::text[], 'The chef "Operação" module (POS/bills) is orders in V2; coarser.'),
151
- ('restaurant_orders', 'Restaurante', 'Pedidos / Comandas', true, true, true, 'mapped', 'feature', 'orders', 'orders.read', '{}'::text[], 'Bills/comandas are orders (ADR 0004).'),
152
- ('restaurant_menu', 'Restaurante', 'Cardápio', true, true, true, 'mapped', 'feature', 'menu', 'menu.read', '{}'::text[], 'plugin-menu gates on menu.* (referenced feature).'),
153
- ('restaurant_product_prices', NULL, NULL, false, NULL, true, 'mapped', 'key', NULL, 'menu.edit', '{}'::text[], 'Edit menu product prices. Not seeded by any migration in the V1 repo.'),
154
- ('restaurant_product_toggle_active', NULL, NULL, false, NULL, true, 'mapped', 'key', NULL, 'menu.edit', '{}'::text[], 'Toggle a menu product. Not seeded by any migration in the V1 repo.'),
155
- ('restaurant_delivery', 'Restaurante', 'Delivery', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced; delivery has no V2 surface.'),
156
- ('restaurant_kitchen', 'Restaurante', 'Cozinha / Painéis', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: orders.read (kitchen role template already reads orders).'),
157
- ('register_bank_accounts', 'Cadastros', 'Contas Bancárias', true, true, true, 'mapped', 'feature', 'financial', 'financial.read', '{}'::text[], 'plg_financial_bank_accounts.'),
158
- ('register_contacts', 'Cadastros', 'Contatos', true, true, true, 'mapped', 'feature', 'people', 'people.read', '{}'::text[], 'Contacts are people (PRD 03).'),
159
- ('register_employees', 'Cadastros', 'Funcionários', true, true, true, 'mapped', 'feature', 'people', 'people.read', '{}'::text[], 'Employees are people with a role (ADR 0003); membership itself is members.*.'),
160
- ('register_professionals', 'Cadastros', 'Profissionais', true, true, true, 'mapped', 'feature', 'people', 'people.read', '{}'::text[], 'Professionals are people with a role (ADR 0003).'),
161
- ('register_suppliers', 'Cadastros', 'Fornecedores', true, true, true, 'mapped', 'feature', 'people', 'people.read', '{}'::text[], 'Suppliers are people (PRD 03).'),
162
- ('register_partnerships', 'Cadastros', 'Parcerias', true, true, true, 'mapped', 'feature', 'people', 'people.read', '{}'::text[], 'Partners are people of kind partner (PRD 03); coarser.'),
163
- ('register_origins', 'Cadastros', 'Origens', true, true, true, 'mapped', 'feature', 'people', 'people.read', '{}'::text[], 'Client origins are a people attribute registry; coarser.'),
164
- ('register_services', 'Cadastros', 'Serviços', true, true, true, 'mapped', 'feature', 'catalog', 'catalog.read', '{}'::text[], 'Services are catalog items (public.services, PRD 04).'),
165
- ('register_equipment', 'Cadastros', 'Equipamentos', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (Header) but equipment has no V2 surface.'),
166
- ('register_locations', 'Cadastros', 'Locais Operacionais', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (Header). service_locations are inside a unit, an agenda extension in Phase 2 (PRD 02 R1) — not units.'),
167
- ('register_pet_species', NULL, NULL, false, NULL, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Pet vertical registry; no V2 surface. Not seeded by any migration in the V1 repo.'),
168
- ('sales_quotes', 'Vendas', 'Orçamentos', true, true, true, 'mapped', 'feature', 'crm.quotes', 'crm.quotes.read', '{}'::text[], 'plugin-crm quotes.'),
169
- ('sales_packages', 'Vendas', 'Pacotes de Serviço', true, true, true, 'mapped', 'feature', 'catalog', 'catalog.read', '{}'::text[], 'Service packages are catalog items (kits, PRD 04).'),
170
- ('sales_contracts', 'Vendas', 'Contratos', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (Header) but contracts have no V2 surface.'),
171
- ('service_execution_manual', 'Atendimento', 'Execução manual de serviço', true, true, true, 'mapped', 'key', NULL, 'orders.edit', '{}'::text[], 'Register a service as executed outside the agenda flow: an order-item edit (ADR 0004).'),
172
- ('reports_dashboard', 'Relatórios', 'Relatórios', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'The reports home.'),
173
- ('reports_panels', 'Relatórios', 'Painéis Customizados', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'Custom panels; coarser.'),
174
- ('reports_agenda', 'Relatórios', 'Relatórios de Agenda', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'V2 report cards are owned by the domain plugin and gate on reports.read + the domain’s read; coarser.'),
175
- ('reports_clientes', 'Relatórios', 'Relatórios de Clientes', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'See reports_agenda.'),
176
- ('reports_estoque', 'Relatórios', 'Relatórios de Estoque', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'See reports_agenda.'),
177
- ('reports_financeiro', 'Relatórios', 'Relatórios Financeiros', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'See reports_agenda; money reports additionally need financial.read at the card.'),
178
- ('reports_gestao', 'Relatórios', 'Relatórios de Gestão', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'See reports_agenda.'),
179
- ('reports_marketing', 'Relatórios', 'Relatórios de Marketing', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'See reports_agenda.'),
180
- ('reports_profissionais', 'Relatórios', 'Relatórios de Profissionais', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'See reports_agenda.'),
181
- ('reports_servicos', 'Relatórios', 'Relatórios de Serviços', true, true, true, 'mapped', 'feature', 'reports', 'reports.read', '{}'::text[], 'See reports_agenda.'),
182
- ('reports_view', 'Relatórios', 'Relatórios', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Inactive since the 2026-05-12 reseed; reports_* superseded it.'),
183
- ('special_qr_access_issue', 'Ações Especiais', 'Liberar acesso por QR Code', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (Header); QR-code unit access has no V2 surface.'),
184
- ('special_qr_access_required', 'Ações Especiais', 'Exigir liberação por QR Code', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 SQL (user_requires_qr_access); no V2 surface.'),
185
- ('special_time_clock_adjust', 'Ações Especiais', 'Ajustar Registros de Ponto', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (TimeClockRegistry); time clock has no V2 surface.'),
186
- ('special_time_clock_launch_payables', 'Ações Especiais', 'Lançar Ponto em Contas a Pagar', true, true, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (TimeClockRegistry); time clock has no V2 surface.'),
187
- ('special_unmatch_reconciled', NULL, NULL, false, NULL, true, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Enforced in V1 (ReconciliationCard); undo-reconciliation has no V2 key. Not seeded by any migration in the V1 repo.'),
188
- ('special_approve_quote', 'Ações Especiais', 'Aprovar/Rejeitar Orçamento', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: a crm.quotes custom action.'),
189
- ('special_bulk_import', 'Ações Especiais', 'Importação em Massa', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced.'),
190
- ('special_cancel_no_pin', 'Ações Especiais', 'Cancelar Item Sem PIN', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: an orders custom action.'),
191
- ('special_delete_paid_order_item', 'Ações Especiais', 'Excluir Item de Pedido Pago', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: an orders custom action.'),
192
- ('special_discount_no_pin', 'Ações Especiais', 'Aplicar Desconto Sem PIN', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: an orders custom action.'),
193
- ('special_edit_paid_financial', 'Ações Especiais', 'Editar Lançamento com Pagamento', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: a financial custom action.'),
194
- ('special_edit_payment_history', 'Ações Especiais', 'Editar Histórico de Pagamentos', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: a financial custom action.'),
195
- ('special_export_sensitive', 'Ações Especiais', 'Exportar Relatórios Sensíveis', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: a reports custom action.'),
196
- ('special_reopen_closed_bill', 'Ações Especiais', 'Reabrir Comanda Fechada', true, true, false, 'backlog', NULL, NULL, NULL, '{}'::text[], 'Never enforced. Natural target: an orders custom action.'),
197
- ('special_other_user_cash', 'Ações Especiais', 'Acessar Caixa de Outro Usuário', true, false, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Deactivated by 20260803150000; superseded by financial_cash_review / financial.read_all.'),
198
- ('special_super_admin', 'Ações Especiais', 'Acessar Super Admin', true, true, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'Platform super-admin is not a tenant permission in V2 (no bypass in code, R9).'),
199
- ('permissions_enforcement_enabled', 'general_settings', NULL, false, NULL, false, 'dropped', NULL, NULL, NULL, '{}'::text[], 'general_settings flag, not a code: RLS is the law (PRD 02 R4). Never migrates.')
200
- ON CONFLICT (v1_code) DO UPDATE SET
201
- v1_category = EXCLUDED.v1_category, v1_name = EXCLUDED.v1_name,
202
- seeded_in_repo = EXCLUDED.seeded_in_repo, active_in_v1 = EXCLUDED.active_in_v1, enforced_in_v1 = EXCLUDED.enforced_in_v1,
203
- status = EXCLUDED.status, kind = EXCLUDED.kind, v2_feature = EXCLUDED.v2_feature, v2_key = EXCLUDED.v2_key,
204
- v2_extra_keys = EXCLUDED.v2_extra_keys, note = EXCLUDED.note, updated_at = now();
205
-
206
- -- ── every target must exist in the catalog (060 ran first) ──────────────
207
- -- A mapping onto a key the catalog does not have is a typo, not a decision:
208
- -- fail the migration rather than let the extractor grant nothing silently.
209
- DO $$
210
- DECLARE v_missing text;
211
- BEGIN
212
- SELECT string_agg(k, ', ' ORDER BY k) INTO v_missing FROM (
213
- SELECT m.v2_feature || '.read' AS k FROM app.v1_permission_map m WHERE m.kind = 'feature'
214
- AND NOT EXISTS (SELECT 1 FROM app.permissions p WHERE p.key = m.v2_feature || '.read')
215
- UNION
216
- SELECT unnest(m.v2_extra_keys) FROM app.v1_permission_map m
217
- EXCEPT
218
- SELECT p.key FROM app.permissions p
219
- ) s;
220
- IF v_missing IS NOT NULL THEN
221
- RAISE EXCEPTION 'v1_permission_map: targets missing from app.permissions: %', v_missing;
222
- END IF;
223
- END $$;
224
-
225
- -- ── the expansion: one V1 rule detail → the V2 keys to grant ────────────
226
- -- kind='feature': view→F.read, insert→F.create, edit→F.edit, delete→F.delete;
227
- -- when the action key does not exist for that feature (settings/tenant/units/
228
- -- roles have read+manage only) the write flags fall back to F.manage.
229
- -- kind='key': any true flag grants v2_key. Extra keys ride along whenever any
230
- -- flag is true. Unknown/backlog/dropped codes expand to nothing.
231
- CREATE OR REPLACE FUNCTION app.v1_permission_keys(
232
- p_code text, p_view boolean DEFAULT false, p_insert boolean DEFAULT false, p_edit boolean DEFAULT false, p_delete boolean DEFAULT false
233
- ) RETURNS text[]
234
- LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path = ''
235
- AS $$
236
- DECLARE
237
- m app.v1_permission_map%ROWTYPE;
238
- out text[] := '{}';
239
- any_flag boolean := coalesce(p_view, false) OR coalesce(p_insert, false) OR coalesce(p_edit, false) OR coalesce(p_delete, false);
240
- BEGIN
241
- SELECT * INTO m FROM app.v1_permission_map WHERE v1_code = p_code;
242
- IF NOT FOUND OR m.status <> 'mapped' OR NOT any_flag THEN
243
- RETURN '{}';
244
- END IF;
245
- IF m.kind = 'key' THEN
246
- out := ARRAY[m.v2_key];
247
- ELSE
248
- IF coalesce(p_view, false) THEN out := out || (m.v2_feature || '.read'); END IF;
249
- IF coalesce(p_insert, false) THEN out := out || CASE WHEN EXISTS (SELECT 1 FROM app.permissions WHERE key = m.v2_feature || '.create') THEN m.v2_feature || '.create' ELSE m.v2_feature || '.manage' END; END IF;
250
- IF coalesce(p_edit, false) THEN out := out || CASE WHEN EXISTS (SELECT 1 FROM app.permissions WHERE key = m.v2_feature || '.edit') THEN m.v2_feature || '.edit' ELSE m.v2_feature || '.manage' END; END IF;
251
- IF coalesce(p_delete, false) THEN out := out || CASE WHEN EXISTS (SELECT 1 FROM app.permissions WHERE key = m.v2_feature || '.delete') THEN m.v2_feature || '.delete' ELSE m.v2_feature || '.manage' END; END IF;
252
- END IF;
253
- out := out || m.v2_extra_keys;
254
- -- only keys the catalog knows, deduplicated, stable order
255
- SELECT coalesce(array_agg(DISTINCT k ORDER BY k), '{}') INTO out
256
- FROM unnest(out) k WHERE EXISTS (SELECT 1 FROM app.permissions p WHERE p.key = k);
257
- RETURN out;
258
- END $$;
259
- REVOKE ALL ON FUNCTION app.v1_permission_keys(text, boolean, boolean, boolean, boolean) FROM public, anon;
260
- GRANT EXECUTE ON FUNCTION app.v1_permission_keys(text, boolean, boolean, boolean, boolean) TO authenticated, service_role;
261
-
262
- -- Read view for tooling/UI (security_invoker; the table is readable by any signed-in user).
263
- CREATE OR REPLACE VIEW public.v_authz_v1_permission_map WITH (security_invoker = true) AS
264
- SELECT v1_code, v1_category, v1_name, seeded_in_repo, active_in_v1, enforced_in_v1, status, kind, v2_feature, v2_key, v2_extra_keys, note
265
- FROM app.v1_permission_map;
266
- GRANT SELECT ON public.v_authz_v1_permission_map TO authenticated, service_role;