@fayz-ai/db 0.13.0 → 0.15.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 (198) 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 +120 -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/migrations/029_o_administrador_enxerga_o_que_existe.sql +167 -0
  33. package/migrations/031_ticketcontrol_joins_the_family.sql +109 -0
  34. package/migrations/032_a_marca_e_um_conjunto_de_tokens.sql +291 -0
  35. package/migrations/041_a_entrega_tem_onde_guardar_a_politica.sql +53 -0
  36. package/migrations/042_o_token_de_marca_fecha_a_porta_anon.sql +17 -0
  37. package/migrations/043_fiscalcontrol_joins_the_family.sql +75 -0
  38. package/migrations/044_o_teste_gratis_dura_trinta_dias.sql +15 -0
  39. package/migrations/046_the_tick_advances_the_flows.sql +77 -0
  40. package/migrations/047_the_tick_sweeps_the_offers.sql +74 -0
  41. package/migrations/052_fullcontrol_joins_the_family.sql +213 -0
  42. package/migrations/053_o_erp_para_de_exigir_o_que_nao_desenha.sql +37 -0
  43. package/package.json +1 -1
  44. package/migrations/0000_legacy_quarantine.sql +0 -86
  45. package/migrations/0000b_straggler_sweep.sql +0 -37
  46. package/migrations/000_core_v1_convert.sql +0 -343
  47. package/migrations/001_core.sql +0 -372
  48. package/migrations/002_rls_user_tenant_ids.sql +0 -64
  49. package/migrations/003_invitations.sql +0 -17
  50. package/migrations/004_archetypes.sql +0 -343
  51. package/migrations/005_locations_archetype.sql +0 -18
  52. package/migrations/006_archetype_rls.sql +0 -74
  53. package/migrations/007_archetype_grants.sql +0 -4
  54. package/migrations/008_grants.sql +0 -5
  55. package/migrations/009_anon_hardening.sql +0 -19
  56. package/migrations/010_migration_ledger.sql +0 -46
  57. package/migrations/011_anon_write_revoke.sql +0 -12
  58. package/migrations/012_rename_migration_ledger.sql +0 -61
  59. package/migrations/013_sequences_rls.sql +0 -22
  60. package/migrations/014_plan_entitlements.sql +0 -28
  61. package/migrations/015_agent_guard.sql +0 -108
  62. package/migrations/016_agent_guard_actor.sql +0 -102
  63. package/migrations/017_core_addresses.sql +0 -115
  64. package/migrations/018_global_search.sql +0 -482
  65. package/migrations/019_tenant_members_person_id.sql +0 -20
  66. package/migrations/020_fayz_projects.sql +0 -63
  67. package/migrations/021_tenant_roles.sql +0 -74
  68. package/migrations/022_invite_acceptance.sql +0 -91
  69. package/migrations/023_team_visibility.sql +0 -75
  70. package/migrations/024_analytics_engine.sql +0 -317
  71. package/migrations/025_created_by.sql +0 -75
  72. package/migrations/026_audit_trail.sql +0 -73
  73. package/migrations/027_domain_events.sql +0 -266
  74. package/migrations/028_tenant_scoped_token.sql +0 -127
  75. package/migrations/029_connections.sql +0 -186
  76. package/migrations/030_effect_idempotency.sql +0 -159
  77. package/migrations/031_sync_run_message.sql +0 -39
  78. package/migrations/032_connection_secrets.sql +0 -227
  79. package/migrations/033_sync_schedule.sql +0 -651
  80. package/migrations/034_custom_fields.sql +0 -55
  81. package/migrations/035_field_registry.sql +0 -148
  82. package/migrations/036_analytics_run_batch.sql +0 -84
  83. package/migrations/037_sync_tick_one_at_a_time.sql +0 -256
  84. package/migrations/038_onboarding_responses.sql +0 -103
  85. package/migrations/039_unit_tree.sql +0 -270
  86. package/migrations/040_resource_grants.sql +0 -474
  87. package/migrations/041_scoped_columns.sql +0 -192
  88. package/migrations/042_unit_scope_policies.sql +0 -145
  89. package/migrations/043_view_invoker.sql +0 -90
  90. package/migrations/044_unit_member_facts.sql +0 -47
  91. package/migrations/045_unit_entry.sql +0 -236
  92. package/migrations/046_membership_visible_to_members.sql +0 -85
  93. package/migrations/047_tasks.sql +0 -266
  94. package/migrations/048_every_login_is_a_person.sql +0 -190
  95. package/migrations/049_bookable_people.sql +0 -126
  96. package/migrations/050_authz_core.sql +0 -230
  97. package/migrations/051_authz_helpers.sql +0 -330
  98. package/migrations/052_authz_fanout.sql +0 -253
  99. package/migrations/053_authz_catalog_templates.sql +0 -402
  100. package/migrations/060_tenancy_seam.sql +0 -132
  101. package/migrations/061_create_tenant.sql +0 -125
  102. package/migrations/062_invitations.sql +0 -329
  103. package/migrations/063_legacy_tenancy_retired.sql +0 -568
  104. package/migrations/064_agent_guard_authz.sql +0 -118
  105. package/migrations/064b_supersede_unit_scope.sql +0 -205
  106. package/migrations/065_scaffold_sweep.sql +0 -139
  107. package/migrations/066_shadow_report.sql +0 -122
  108. package/migrations/070_permission_catalog.sql +0 -205
  109. package/migrations/071_v1_permission_map.sql +0 -266
  110. package/migrations/072_role_rpcs.sql +0 -126
  111. package/migrations/073_legacy_rbac_retire.sql +0 -471
  112. package/migrations/075_company_legal_entities.sql +0 -169
  113. package/migrations/076_tenant_settings.sql +0 -251
  114. package/migrations/080_people_roles.sql +0 -269
  115. package/migrations/081_people_identity.sql +0 -271
  116. package/migrations/082_people_membership_link.sql +0 -142
  117. package/migrations/083_people_data_migration.sql +0 -75
  118. package/migrations/084_people_registrations_tokens.sql +0 -282
  119. package/migrations/085_catalog_products.sql +0 -333
  120. package/migrations/086_catalog_pricing.sql +0 -194
  121. package/migrations/087_catalog_packages.sql +0 -134
  122. package/migrations/090_orders_venda.sql +0 -166
  123. package/migrations/091_orders_scaffold.sql +0 -92
  124. package/migrations/095_config_field_rules.sql +0 -261
  125. package/migrations/096_audit_append_only.sql +0 -256
  126. package/migrations/097_sequences_authorized.sql +0 -111
  127. package/migrations/098_holidays.sql +0 -80
  128. package/migrations/099_access_grants.sql +0 -293
  129. package/migrations/100_migration_schema.sql +0 -217
  130. package/migrations/101_migration_allowlist.sql +0 -202
  131. package/migrations/102_migration_rpcs.sql +0 -933
  132. package/migrations/103_migration_reconcile_ponr.sql +0 -132
  133. package/migrations/105_policies_to_authenticated.sql +0 -71
  134. package/migrations/106_function_search_path.sql +0 -55
  135. package/migrations/107_core_table_prefix.sql +0 -361
  136. package/migrations/108_authz_write_guards.sql +0 -149
  137. package/migrations/109_catalog_migration_promoted_columns.sql +0 -126
  138. package/migrations/110_people_kind_vocabulary.sql +0 -120
  139. package/migrations/111_migration_excluded_is_a_decision.sql +0 -259
  140. package/migrations/111_replacing_a_view_keeps_its_dependents.sql +0 -132
  141. package/migrations/112_money_precision_standard.sql +0 -132
  142. package/migrations/113_addresses_units_companies.sql +0 -114
  143. package/migrations/114_migrations_ledger_immutable.sql +0 -65
  144. package/migrations/115_registration_honours_field_rules.sql +0 -172
  145. package/migrations/116_field_rules_check_needs_a_tenant.sql +0 -72
  146. package/migrations/117_authz_reconciliation_schedule.sql +0 -82
  147. package/migrations/118_migration_catalog_writers.sql +0 -450
  148. package/migrations/119_migration_config_writers.sql +0 -193
  149. package/migrations/120_migration_facet_writer.sql +0 -139
  150. package/migrations/121_migration_financial_writers.sql +0 -294
  151. package/migrations/122_migration_inventory_writers.sql +0 -245
  152. package/migrations/123_migration_order_item_writer.sql +0 -144
  153. package/migrations/124_migration_ledger_writers.sql +0 -170
  154. package/migrations/125_migration_authz_people_writers.sql +0 -205
  155. package/migrations/126_owner_scoping_is_configuration.sql +0 -247
  156. package/migrations/127_scaffold_audit_hook.sql +0 -98
  157. package/migrations/128_shadow_tables_enforced.sql +0 -93
  158. package/migrations/129_order_kind_terminal_states.sql +0 -57
  159. package/migrations/130_every_login_is_a_person.sql +0 -196
  160. package/migrations/131_migration_invoice_split.sql +0 -127
  161. package/migrations/132_audit_prune_scheduled.sql +0 -28
  162. package/migrations/133_unit_is_a_session_property.sql +0 -155
  163. package/migrations/134_field_rules_on_read.sql +0 -341
  164. package/migrations/135_distribution_polarity.sql +0 -158
  165. package/migrations/136_unit_id_means_locality.sql +0 -358
  166. package/migrations/137_vendor_named_spine_objects.sql +0 -126
  167. package/migrations/138_grants_inherit_down_the_tree.sql +0 -178
  168. package/migrations/139_distributable_is_a_scaffold_option.sql +0 -109
  169. package/migrations/140_masking_is_a_scaffold_option.sql +0 -85
  170. package/migrations/141_renamed_objects_keep_a_compat_name.sql +0 -192
  171. package/migrations/142_a_person_has_addresses.sql +0 -212
  172. package/migrations/143_a_professional_has_a_rate.sql +0 -75
  173. package/migrations/144_a_product_can_be_sold_in_sizes.sql +0 -57
  174. package/migrations/145_the_app_says_which_tenant_it_is_in.sql +0 -123
  175. package/migrations/146_products_stock_has_one_writer.sql +0 -67
  176. package/migrations/147_every_archetype_has_a_kind_registry.sql +0 -388
  177. package/migrations/148_the_legacy_archetype_stops_being_writable.sql +0 -154
  178. package/migrations/149_the_event_log_gets_a_consumer.sql +0 -331
  179. package/migrations/150_the_app_is_configured_in_the_database.sql +0 -285
  180. package/migrations/151_stock_balance_is_an_archetype.sql +0 -144
  181. package/migrations/152_a_file_is_an_archetype.sql +0 -222
  182. package/migrations/153_a_plugin_calls_a_service_through_one_door.sql +0 -199
  183. package/migrations/154_the_plan_is_a_ceiling.sql +0 -258
  184. package/migrations/155_a_tenant_can_leave.sql +0 -271
  185. package/migrations/156_the_service_door_has_a_server_side.sql +0 -335
  186. package/migrations/157_nobody_creates_objects_in_public.sql +0 -74
  187. package/migrations/158_the_registry_owns_the_status_vocabulary.sql +0 -153
  188. package/migrations/159_the_plan_catalogue_gets_its_first_rows.sql +0 -132
  189. package/migrations/160_the_vertical_decides_what_starts_on.sql +0 -246
  190. package/migrations/161_a_tenant_leaves_with_its_data.sql +0 -363
  191. package/migrations/162_every_name_has_one_creator_for_real.sql +0 -126
  192. package/migrations/163_a_species_nobody_declared_goes_to_quarantine.sql +0 -184
  193. package/migrations/164_the_sequence_table_joins_the_register.sql +0 -26
  194. package/migrations/165_a_view_is_not_a_way_in.sql +0 -90
  195. package/migrations/166_the_platform_billing_leftovers_go.sql +0 -72
  196. package/migrations/167_a_view_gets_back_what_its_table_grants.sql +0 -112
  197. package/migrations/168_the_grant_census_stops_crying_wolf.sql +0 -33
  198. 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;