@jantstack/adonis-authz 1.0.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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +138 -0
  3. package/build/commands/main.d.ts +7 -0
  4. package/build/commands/main.d.ts.map +1 -0
  5. package/build/commands/main.js +7 -0
  6. package/build/commands/main.js.map +1 -0
  7. package/build/commands/openfga_import.d.ts +28 -0
  8. package/build/commands/openfga_import.d.ts.map +1 -0
  9. package/build/commands/openfga_import.js +74 -0
  10. package/build/commands/openfga_import.js.map +1 -0
  11. package/build/commands/openfga_provision.d.ts +27 -0
  12. package/build/commands/openfga_provision.d.ts.map +1 -0
  13. package/build/commands/openfga_provision.js +73 -0
  14. package/build/commands/openfga_provision.js.map +1 -0
  15. package/build/configure.d.ts +10 -0
  16. package/build/configure.d.ts.map +1 -0
  17. package/build/configure.js +43 -0
  18. package/build/configure.js.map +1 -0
  19. package/build/index.d.ts +21 -0
  20. package/build/index.d.ts.map +1 -0
  21. package/build/index.js +18 -0
  22. package/build/index.js.map +1 -0
  23. package/build/providers/authz_provider.d.ts +17 -0
  24. package/build/providers/authz_provider.d.ts.map +1 -0
  25. package/build/providers/authz_provider.js +21 -0
  26. package/build/providers/authz_provider.js.map +1 -0
  27. package/build/services/main.d.ts +10 -0
  28. package/build/services/main.d.ts.map +1 -0
  29. package/build/services/main.js +13 -0
  30. package/build/services/main.js.map +1 -0
  31. package/build/src/catalog.d.ts +3 -0
  32. package/build/src/catalog.d.ts.map +1 -0
  33. package/build/src/catalog.js +97 -0
  34. package/build/src/catalog.js.map +1 -0
  35. package/build/src/define_config.d.ts +53 -0
  36. package/build/src/define_config.d.ts.map +1 -0
  37. package/build/src/define_config.js +4 -0
  38. package/build/src/define_config.js.map +1 -0
  39. package/build/src/drivers/database_driver.d.ts +48 -0
  40. package/build/src/drivers/database_driver.d.ts.map +1 -0
  41. package/build/src/drivers/database_driver.js +260 -0
  42. package/build/src/drivers/database_driver.js.map +1 -0
  43. package/build/src/drivers/openfga_driver.d.ts +107 -0
  44. package/build/src/drivers/openfga_driver.d.ts.map +1 -0
  45. package/build/src/drivers/openfga_driver.js +450 -0
  46. package/build/src/drivers/openfga_driver.js.map +1 -0
  47. package/build/src/manager.d.ts +29 -0
  48. package/build/src/manager.d.ts.map +1 -0
  49. package/build/src/manager.js +79 -0
  50. package/build/src/manager.js.map +1 -0
  51. package/build/src/middleware/app_access_middleware.d.ts +23 -0
  52. package/build/src/middleware/app_access_middleware.d.ts.map +1 -0
  53. package/build/src/middleware/app_access_middleware.js +53 -0
  54. package/build/src/middleware/app_access_middleware.js.map +1 -0
  55. package/build/src/models/authz_assignment.d.ts +166 -0
  56. package/build/src/models/authz_assignment.d.ts.map +1 -0
  57. package/build/src/models/authz_assignment.js +60 -0
  58. package/build/src/models/authz_assignment.js.map +1 -0
  59. package/build/src/models/authz_deny.d.ts +161 -0
  60. package/build/src/models/authz_deny.d.ts.map +1 -0
  61. package/build/src/models/authz_deny.js +50 -0
  62. package/build/src/models/authz_deny.js.map +1 -0
  63. package/build/src/models/authz_permission.d.ts +159 -0
  64. package/build/src/models/authz_permission.d.ts.map +1 -0
  65. package/build/src/models/authz_permission.js +42 -0
  66. package/build/src/models/authz_permission.js.map +1 -0
  67. package/build/src/models/authz_role.d.ts +166 -0
  68. package/build/src/models/authz_role.d.ts.map +1 -0
  69. package/build/src/models/authz_role.js +66 -0
  70. package/build/src/models/authz_role.js.map +1 -0
  71. package/build/src/models/authz_role_permission.d.ts +155 -0
  72. package/build/src/models/authz_role_permission.d.ts.map +1 -0
  73. package/build/src/models/authz_role_permission.js +35 -0
  74. package/build/src/models/authz_role_permission.js.map +1 -0
  75. package/build/src/testing/contract.d.ts +27 -0
  76. package/build/src/testing/contract.d.ts.map +1 -0
  77. package/build/src/testing/contract.js +211 -0
  78. package/build/src/testing/contract.js.map +1 -0
  79. package/build/src/testing/main.d.ts +11 -0
  80. package/build/src/testing/main.d.ts.map +1 -0
  81. package/build/src/testing/main.js +10 -0
  82. package/build/src/testing/main.js.map +1 -0
  83. package/build/src/traits/authz_scopes.d.ts +21 -0
  84. package/build/src/traits/authz_scopes.d.ts.map +1 -0
  85. package/build/src/traits/authz_scopes.js +45 -0
  86. package/build/src/traits/authz_scopes.js.map +1 -0
  87. package/build/src/traits/has_uuid.d.ts +151 -0
  88. package/build/src/traits/has_uuid.d.ts.map +1 -0
  89. package/build/src/traits/has_uuid.js +38 -0
  90. package/build/src/traits/has_uuid.js.map +1 -0
  91. package/build/src/types.d.ts +153 -0
  92. package/build/src/types.d.ts.map +1 -0
  93. package/build/src/types.js +38 -0
  94. package/build/src/types.js.map +1 -0
  95. package/build/stubs/config/app_acl.stub +81 -0
  96. package/build/stubs/config/authorization.stub +74 -0
  97. package/build/stubs/main.d.ts +3 -0
  98. package/build/stubs/main.d.ts.map +1 -0
  99. package/build/stubs/main.js +3 -0
  100. package/build/stubs/main.js.map +1 -0
  101. package/build/stubs/migration.stub +124 -0
  102. package/package.json +94 -0
@@ -0,0 +1,151 @@
1
+ import type { BaseModel } from '@adonisjs/lucid/orm';
2
+ import type { NormalizeConstructor } from '@adonisjs/core/types/helpers';
3
+ /**
4
+ * Trait para asignar automáticamente UUIDv7 en la PK del modelo.
5
+ * Autodetecta correctamente la primaryKey desde la instancia real.
6
+ */
7
+ export declare const hasUuid: <Model extends NormalizeConstructor<typeof BaseModel>>(superclass: Model) => {
8
+ new (...args: any[]): {
9
+ $attributes: import("@adonisjs/lucid/types/model").ModelObject;
10
+ $extras: import("@adonisjs/lucid/types/model").ModelObject;
11
+ $original: import("@adonisjs/lucid/types/model").ModelObject;
12
+ $preloaded: {
13
+ [relation: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
14
+ };
15
+ $sideloaded: import("@adonisjs/lucid/types/model").ModelObject;
16
+ $primaryKeyValue?: number | string;
17
+ $isPersisted: boolean;
18
+ $isNew: boolean;
19
+ $isLocal: boolean;
20
+ $dirty: import("@adonisjs/lucid/types/model").ModelObject;
21
+ $isDirty: boolean;
22
+ $isDeleted: boolean;
23
+ $options?: import("@adonisjs/lucid/types/model").ModelOptions;
24
+ $trx?: import("@adonisjs/lucid/types/database").TransactionClientContract;
25
+ $setOptionsAndTrx(options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): void;
26
+ useTransaction(trx: import("@adonisjs/lucid/types/database").TransactionClientContract): /*elided*/ any;
27
+ useConnection(connection: string): /*elided*/ any;
28
+ $getQueryFor(action: "insert", client: import("@adonisjs/lucid/types/database").QueryClientContract): ReturnType<import("@adonisjs/lucid/types/database").QueryClientContract["insertQuery"]>;
29
+ $getQueryFor(action: "update" | "delete" | "refresh", client: import("@adonisjs/lucid/types/database").QueryClientContract): import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<import("@adonisjs/lucid/types/model").LucidModel>;
30
+ $setAttribute(key: string, value: any): void;
31
+ $getAttribute(key: string): any;
32
+ $getAttributeFromCache(key: string, callback: import("@adonisjs/lucid/types/model").CacheNode["getter"]): any;
33
+ $hasRelated(key: string): boolean;
34
+ $setRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
35
+ $pushRelated(key: string, result: import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | null): void;
36
+ $getRelated(key: string, defaultValue?: any): import("@adonisjs/lucid/types/querybuilder").OneOrMany<import("@adonisjs/lucid/types/model").LucidRow> | undefined | null;
37
+ $consumeAdapterResult(adapterResult: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject): void;
38
+ $hydrateOriginals(): void;
39
+ fill(value: Partial<import("@adonisjs/lucid/types/model").ModelAttributes</*elided*/ any>>, allowExtraProperties?: boolean): /*elided*/ any;
40
+ merge(value: Partial<import("@adonisjs/lucid/types/model").ModelAttributes</*elided*/ any>>, allowExtraProperties?: boolean): /*elided*/ any;
41
+ isDirty(fields?: undefined[] | undefined): boolean;
42
+ enableForceUpdate(): /*elided*/ any;
43
+ save(): Promise</*elided*/ any>;
44
+ saveQuietly(): Promise</*elided*/ any>;
45
+ lockForUpdate<T>(callback: (user: /*elided*/ any) => T | Promise<T>): Promise<T>;
46
+ delete(): Promise<void>;
47
+ deleteQuietly(): Promise<void>;
48
+ refresh(): Promise</*elided*/ any>;
49
+ load: import("@adonisjs/lucid/types/model").LucidRowPreload</*elided*/ any>;
50
+ loadOnce: import("@adonisjs/lucid/types/model").LucidRowPreloadOnce</*elided*/ any>;
51
+ preload: import("@adonisjs/lucid/types/model").LucidRowPreload</*elided*/ any>;
52
+ loadAggregate: <Self extends /*elided*/ any, Name extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder = NonNullable<Self[Name]> extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? (import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> & Self[Name] & {})["subQuery"] : never>(name: Name, callback: (builder: RelatedBuilder) => void) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
53
+ loadCount: <Self extends /*elided*/ any, Name_1 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<Self>, RelatedBuilder_1 = NonNullable<Self[Name_1]> extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? (import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> & Self[Name_1] & {})["subQuery"] : never>(name: Name_1, callback?: ((builder: RelatedBuilder_1) => void) | undefined) => import("@adonisjs/lucid/types/model").LazyLoadAggregatesContract<Self>;
54
+ serializeAttributes(fields?: import("@adonisjs/lucid/types/model").CherryPickFields, raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
55
+ serializeComputed(fields?: import("@adonisjs/lucid/types/model").CherryPickFields): import("@adonisjs/lucid/types/model").ModelObject;
56
+ serializeRelations(fields: undefined, raw: true): {
57
+ [key: string]: import("@adonisjs/lucid/types/model").LucidRow | import("@adonisjs/lucid/types/model").LucidRow[];
58
+ };
59
+ serializeRelations(cherryPick: import("@adonisjs/lucid/types/model").CherryPick["relations"] | undefined, raw: false | undefined): import("@adonisjs/lucid/types/model").ModelObject;
60
+ serializeRelations(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick["relations"], raw?: boolean): import("@adonisjs/lucid/types/model").ModelObject;
61
+ serialize(cherryPick?: import("@adonisjs/lucid/types/model").CherryPick): import("@adonisjs/lucid/types/model").ModelObject;
62
+ toObject(): import("@adonisjs/lucid/types/model").ModelObject;
63
+ toJSON(): import("@adonisjs/lucid/types/model").ModelObject;
64
+ toAttributes(): Record<string, any>;
65
+ related<Name_2 extends undefined>(relation: Name_2): NonNullable</*elided*/ any[Name_2]> extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? (import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> & /*elided*/ any[Name_2] & {})["client"] : never;
66
+ };
67
+ selfAssignPrimaryKey: boolean;
68
+ generateUuid(model: any): void;
69
+ /** Devuelve un nuevo UUID v7 (para uso en pivots u otros datos que no son instancias del modelo). */
70
+ nextUuid(): string;
71
+ find: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
72
+ readonly booted: boolean;
73
+ $columnsDefinitions: Map<string, import("@adonisjs/lucid/types/model").ModelColumnOptions>;
74
+ $relationsDefinitions: Map<string, import("@adonisjs/lucid/types/relations").RelationshipsContract>;
75
+ $computedDefinitions: Map<string, import("@adonisjs/lucid/types/model").ComputedOptions>;
76
+ primaryKey: string;
77
+ connection?: string | undefined;
78
+ namingStrategy: import("@adonisjs/lucid/types/model").NamingStrategyContract;
79
+ table: string;
80
+ $adapter: import("@adonisjs/lucid/types/model").AdapterContract;
81
+ useAdapter: (adapter: import("@adonisjs/lucid/types/model").AdapterContract) => void;
82
+ $hooks: import("@poppinss/hooks").default<any>;
83
+ $keys: {
84
+ attributesToColumns: import("@adonisjs/lucid/types/model").ModelKeysContract;
85
+ attributesToSerialized: import("@adonisjs/lucid/types/model").ModelKeysContract;
86
+ columnsToAttributes: import("@adonisjs/lucid/types/model").ModelKeysContract;
87
+ columnsToSerialized: import("@adonisjs/lucid/types/model").ModelKeysContract;
88
+ serializedToColumns: import("@adonisjs/lucid/types/model").ModelKeysContract;
89
+ serializedToAttributes: import("@adonisjs/lucid/types/model").ModelKeysContract;
90
+ columnAliasesToAttributes: import("@adonisjs/lucid/types/model").ModelKeysContract;
91
+ };
92
+ $createFromAdapterResult: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, result?: import("@adonisjs/lucid/types/model").ModelObject, sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => null | InstanceType<T>;
93
+ $createMultipleFromAdapterResult: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, results: import("@adonisjs/lucid/types/model").ModelObject[], sideloadAttributes?: import("@adonisjs/lucid/types/model").ModelObject, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => InstanceType<T>[];
94
+ $addColumn: (name: string, options: Partial<import("@adonisjs/lucid/types/model").ColumnOptions>) => import("@adonisjs/lucid/types/model").ColumnOptions;
95
+ $hasColumn: (name: string) => boolean;
96
+ $getColumn: (name: string) => import("@adonisjs/lucid/types/model").ModelColumnOptions | undefined;
97
+ $getColumnAlias: (columnName: string) => string;
98
+ columnsForSelect: () => Record<string, string>;
99
+ $addComputed: (name: string, options: Partial<import("@adonisjs/lucid/types/model").ComputedOptions>) => import("@adonisjs/lucid/types/model").ComputedOptions;
100
+ $hasComputed: (name: string) => boolean;
101
+ $getComputed: (name: string) => import("@adonisjs/lucid/types/model").ComputedOptions | undefined;
102
+ $addRelation: (name: string, type: import("@adonisjs/lucid/types/relations").ModelRelationTypes["__opaque_type"], relatedModel: () => import("@adonisjs/lucid/types/model").LucidModel, options: import("@adonisjs/lucid/types/model").ModelRelationOptions) => void;
103
+ $hasRelation: (name: string) => boolean;
104
+ $getRelation: {
105
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Name_2 extends import("@adonisjs/lucid/types/relations").ExtractModelRelations<InstanceType<Model_1>>>(this: Model_1, name: Name_2): NonNullable<InstanceType<Model_1>[Name_2]> extends import("@adonisjs/lucid/types/relations").ModelRelations<import("@adonisjs/lucid/types/model").LucidModel, import("@adonisjs/lucid/types/model").LucidModel> ? NonNullable<InstanceType<Model_1>[Name_2]>["client"]["relation"] : import("@adonisjs/lucid/types/relations").RelationshipsContract;
106
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, name: string): import("@adonisjs/lucid/types/relations").RelationshipsContract;
107
+ };
108
+ $defineProperty: <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Prop extends keyof Model_1>(this: Model_1, propertyName: Prop, defaultValue: Model_1[Prop], strategy: "inherit" | "define" | ((value: Model_1[Prop]) => Model_1[Prop])) => void;
109
+ boot: () => void;
110
+ before: {
111
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Event extends "find" | "fetch">(this: Model_1, event: Event, handler: import("@adonisjs/lucid/types/model").HooksHandler<import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1>, Event>): void;
112
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<[import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1>, import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1>], "paginate">): void;
113
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Event_1 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_1, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_1>): void;
114
+ };
115
+ after: {
116
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, event: "fetch", handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>[], "fetch">): void;
117
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel>(this: Model_1, event: "paginate", handler: import("@adonisjs/lucid/types/model").HooksHandler<import("@adonisjs/lucid/types/model").ModelPaginatorContract<InstanceType<Model_1>>, "paginate">): void;
118
+ <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Event_2 extends import("@adonisjs/lucid/types/model").EventsList>(this: Model_1, event: Event_2, handler: import("@adonisjs/lucid/types/model").HooksHandler<InstanceType<Model_1>, Event_2>): void;
119
+ };
120
+ create: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
121
+ createQuietly: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
122
+ createMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
123
+ createManyQuietly: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, values: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
124
+ findOrFail: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
125
+ findBy: {
126
+ <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
127
+ <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<null | InstanceType<T>>;
128
+ };
129
+ findByOrFail: {
130
+ <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
131
+ <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>>;
132
+ };
133
+ findManyBy: {
134
+ <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, clause: Record<string, unknown>, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
135
+ <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, key: string, value: any, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions): Promise<InstanceType<T>[]>;
136
+ };
137
+ first: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<null | InstanceType<T>>;
138
+ firstOrFail: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>>;
139
+ findMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, value: any[], options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
140
+ firstOrNew: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
141
+ firstOrCreate: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, savePayload?: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
142
+ updateOrCreate: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, searchPayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, updatePayload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>, options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>>;
143
+ fetchOrNewUpMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
144
+ fetchOrCreateMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
145
+ updateOrCreateMany: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, predicate: keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>> | (keyof import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>)[], payload: Partial<import("@adonisjs/lucid/types/model").ModelAttributes<InstanceType<T>>>[], options?: import("@adonisjs/lucid/types/model").ModelAssignOptions) => Promise<InstanceType<T>[]>;
146
+ all: <T extends import("@adonisjs/lucid/types/model").LucidModel>(this: T, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => Promise<InstanceType<T>[]>;
147
+ query: <Model_1 extends import("@adonisjs/lucid/types/model").LucidModel, Result = InstanceType<Model_1>>(this: Model_1, options?: import("@adonisjs/lucid/types/model").ModelAdapterOptions) => import("@adonisjs/lucid/types/model").ModelQueryBuilderContract<Model_1, Result>;
148
+ transaction: import("@adonisjs/lucid/types/database").TransactionFn;
149
+ truncate: (cascade?: boolean) => Promise<void>;
150
+ } & Model;
151
+ //# sourceMappingURL=has_uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has_uuid.d.ts","sourceRoot":"","sources":["../../../src/traits/has_uuid.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAGxE;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,KAAK,SAAS,oBAAoB,CAAC,OAAO,SAAS,CAAC,EAC1E,YAAY,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAMY,GAAG;IAO9B,qGAAqG;gBAClF,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kaAM0jtB,oDAAiD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SADvotB,CAAA"}
@@ -0,0 +1,38 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { beforeCreate } from '@adonisjs/lucid/orm';
11
+ import { v7 as uuidv7 } from 'uuid';
12
+ /**
13
+ * Trait para asignar automáticamente UUIDv7 en la PK del modelo.
14
+ * Autodetecta correctamente la primaryKey desde la instancia real.
15
+ */
16
+ export const hasUuid = (superclass) => {
17
+ class WithPrimaryUuidClass extends superclass {
18
+ static selfAssignPrimaryKey = true;
19
+ static generateUuid(model) {
20
+ const pk = model.constructor.primaryKey ?? 'id';
21
+ if (!model[pk]) {
22
+ model[pk] = uuidv7();
23
+ }
24
+ }
25
+ /** Devuelve un nuevo UUID v7 (para uso en pivots u otros datos que no son instancias del modelo). */
26
+ static nextUuid() {
27
+ return uuidv7();
28
+ }
29
+ }
30
+ __decorate([
31
+ beforeCreate(),
32
+ __metadata("design:type", Function),
33
+ __metadata("design:paramtypes", [Object]),
34
+ __metadata("design:returntype", void 0)
35
+ ], WithPrimaryUuidClass, "generateUuid", null);
36
+ return WithPrimaryUuidClass;
37
+ };
38
+ //# sourceMappingURL=has_uuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has_uuid.js","sourceRoot":"","sources":["../../../src/traits/has_uuid.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAA;AAEnC;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,UAAiB,EACjB,EAAE;IACF,MAAM,oBAAqB,SAAQ,UAAU;QAC3C,MAAM,CAAC,oBAAoB,GAAG,IAAI,CAAA;QAG3B,AAAP,MAAM,CAAC,YAAY,CAAC,KAAU;YAC5B,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC,UAAU,IAAI,IAAI,CAAA;YAC/C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBACf,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAA;YACtB,CAAC;QACH,CAAC;QAED,qGAAqG;QACrG,MAAM,CAAC,QAAQ;YACb,OAAO,MAAM,EAAE,CAAA;QACjB,CAAC;;IAVM;QADN,YAAY,EAAE;;;;kDAMd;IAOH,OAAO,oBAAoB,CAAA;AAC7B,CAAC,CAAA"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Contrato del sistema de autorización del chasis (puerto + drivers).
3
+ *
4
+ * El chasis NO condena a un backend concreto: todo call-site (middleware,
5
+ * services, seeders) habla con este contrato a través del manager
6
+ * (`#services/authorization/main`). El driver `database` (motor propio sobre
7
+ * las tablas `authz_*`) es el default autosuficiente; un driver `openfga` u
8
+ * otro custom se registra en `config/authorization.ts` sin tocar call-sites.
9
+ *
10
+ * ── Semántica que TODO driver debe respetar ──────────────────────────────
11
+ * La verifica `tests/contracts/authorization_driver_contract.ts` (la misma
12
+ * suite corre contra cada driver — es el juez del contrato):
13
+ *
14
+ * 1. **Scopes jerárquicos, herencia SOLO hacia abajo.** La cadena de un scope
15
+ * es `[scope, ...ancestros]` (`app` es la raíz: su cadena es él mismo).
16
+ * Un grant en un scope autoriza en ese scope y en TODOS sus descendientes;
17
+ * nunca en hermanos ni ancestros. En T1 solo opera `app` (los ancestros de
18
+ * `organization`/`unit` se completan en T2/T3 vía `resolveAncestors`).
19
+ * 2. **Deny explícito gana.** Un deny de un permiso en cualquier scope de la
20
+ * cadena bloquea `authorize`, aunque un rol lo conceda (el deny también
21
+ * hereda hacia abajo). Quitar el deny restaura el permiso.
22
+ * 3. **Expiración observable.** Una asignación con `expiresAt` en el pasado
23
+ * no concede nada; con `expiresAt` futuro concede normalmente.
24
+ * 4. **Holder polimórfico.** `SubjectRef.type` es el morph name del modelo
25
+ * (`users` | `admins` | `integrations` | los del consumidor). Dos holders
26
+ * con el mismo uuid y distinto type JAMÁS se cruzan.
27
+ * 5. **Denegación por defecto.** Permiso desconocido, rol sin el permiso o
28
+ * holder sin asignación vigente → `false`, nunca throw en `authorize`.
29
+ * En cambio `grant`/`deny` con rol/permiso fuera del catálogo → throw
30
+ * (error de programación, no de autorización).
31
+ * 6. **Idempotencia de escritura.** Re-`grant` no duplica (actualiza
32
+ * `expiresAt`); re-`revoke`/re-`deny`/re-`removeDeny` son no-ops seguros.
33
+ */
34
+ /** Referencia polimórfica al holder: morph name + uuid. */
35
+ export interface SubjectRef {
36
+ type: string;
37
+ uuid: string;
38
+ }
39
+ /**
40
+ * Nivel de scope. El motor solo conoce la raíz (`app`, uuid null); los demás
41
+ * niveles los define el CONSUMIDOR — `organization`/`unit` en este chasis,
42
+ * pero podrían ser `project`, `site`, `case`… El árbol lo declara el
43
+ * `ScopeAncestorsResolver` que se inyecta a los drivers, así que el motor no
44
+ * necesita conocer la taxonomía.
45
+ *
46
+ * Un consumidor que quiera seguridad de tipos define su propia unión:
47
+ * type MyScope = 'app' | 'organization' | 'unit'
48
+ */
49
+ export type ScopeType = string;
50
+ /** Nombre reservado del scope raíz. */
51
+ export declare const APP_SCOPE_TYPE = "app";
52
+ export interface ScopeRef {
53
+ type: ScopeType;
54
+ /** `null` solo para `app` (scope global sin entidad). */
55
+ uuid: string | null;
56
+ }
57
+ /** El scope raíz de aplicación (nivel plataforma). */
58
+ export declare const APP_SCOPE: ScopeRef;
59
+ export interface GrantOptions {
60
+ /** Expiración de la asignación. `null`/omitido = sin expiración. */
61
+ expiresAt?: Date | null;
62
+ }
63
+ export interface AuthorizationDriver {
64
+ /**
65
+ * ¿El holder tiene el permiso en el scope? Evalúa la cadena completa:
66
+ * sin deny en la cadena Y alguna asignación vigente cuyo rol concede el
67
+ * permiso. Nunca lanza: desconocido = false.
68
+ */
69
+ authorize(subject: SubjectRef, permission: string, scope: ScopeRef): Promise<boolean>;
70
+ /**
71
+ * Asigna un rol al holder en un scope. El rol debe existir en el catálogo
72
+ * para `scope.type` (throw si no). Idempotente: re-grant actualiza expiresAt.
73
+ */
74
+ grant(subject: SubjectRef, role: string, scope: ScopeRef, options?: GrantOptions): Promise<void>;
75
+ /** Quita la asignación del rol en ese scope exacto. No-op si no existía. */
76
+ revoke(subject: SubjectRef, role: string, scope: ScopeRef): Promise<void>;
77
+ /**
78
+ * ¿El holder tiene el rol (vigente) en el scope o en un ancestro?
79
+ * Misma regla de herencia hacia abajo que `authorize`.
80
+ */
81
+ hasRole(subject: SubjectRef, role: string, scope: ScopeRef): Promise<boolean>;
82
+ /**
83
+ * Deny explícito de UN permiso al holder en un scope (y sus descendientes).
84
+ * El permiso debe existir en el catálogo (throw si no). Idempotente.
85
+ */
86
+ deny(subject: SubjectRef, permission: string, scope: ScopeRef): Promise<void>;
87
+ /** Levanta el deny en ese scope exacto. No-op si no existía. */
88
+ removeDeny(subject: SubjectRef, permission: string, scope: ScopeRef): Promise<void>;
89
+ /** Holders con asignación VIGENTE del rol en ese scope exacto (sin herencia). */
90
+ listSubjects(role: string, scope: ScopeRef): Promise<SubjectRef[]>;
91
+ /** Roles (slugs) con asignación DIRECTA vigente del holder en ese scope exacto. */
92
+ listRoles(subject: SubjectRef, scope: ScopeRef): Promise<string[]>;
93
+ /**
94
+ * Scopes del tipo dado donde el holder tiene alguna asignación DIRECTA
95
+ * vigente de rol. Base de "membresía" (¿de qué organizations es miembro?).
96
+ */
97
+ listRoleScopes(subject: SubjectRef, scopeType: ScopeType): Promise<ScopeRef[]>;
98
+ /**
99
+ * Scopes con asignación DIRECTA vigente que concede el permiso, excluyendo
100
+ * los bloqueados por deny. No enumera descendientes heredados (sería
101
+ * abierto): el caller consulta `authorize` sobre un scope concreto.
102
+ */
103
+ listScopes(subject: SubjectRef, permission: string): Promise<ScopeRef[]>;
104
+ }
105
+ /** Factory registrable en `config/authorization.ts`. */
106
+ export type AuthorizationDriverFactory = () => AuthorizationDriver | Promise<AuthorizationDriver>;
107
+ /**
108
+ * Resolutor de ancestros de un scope (del más cercano a la raíz). El paquete
109
+ * NO conoce el dominio del consumidor: el chasis inyecta el suyo (que sabe de
110
+ * organizations/organization_units) al construir cada driver en el config.
111
+ * Default de los drivers sin resolutor: `app` → [], resto → [APP_SCOPE].
112
+ */
113
+ export type ScopeAncestorsResolver = (scope: ScopeRef) => Promise<ScopeRef[]>;
114
+ /**
115
+ * Escritura del motor, notificada al hook `onWrite` del config. El chasis lo
116
+ * usa para auditar/emitir SSE; un consumidor puede loguear, notificar, etc.
117
+ */
118
+ export interface AuthzWriteEvent {
119
+ action: 'granted' | 'revoked' | 'denied' | 'deny_removed';
120
+ subject: SubjectRef;
121
+ scope: ScopeRef;
122
+ /** Presente en granted/revoked. */
123
+ role?: string;
124
+ /** Presente en denied/deny_removed. */
125
+ permission?: string;
126
+ expiresAt?: Date | null;
127
+ }
128
+ export interface CatalogRoleSpec {
129
+ /** UUID fijo opcional (mismo patrón que organization_acl: estable entre entornos). */
130
+ uuid?: string;
131
+ slug: string;
132
+ /** Nivel al que este rol es asignable. */
133
+ scopeType: ScopeType;
134
+ name?: string;
135
+ description?: string | null;
136
+ /**
137
+ * Rango del rol (mayor = más privilegio). Lo usa la POLICY de asignación
138
+ * del consumidor ("no puedes otorgar/quitar un rol de rango ≥ al tuyo");
139
+ * el motor lo almacena como metadata pero no lo evalúa en authorize().
140
+ */
141
+ rank?: number;
142
+ /** Slugs de permisos (`recurso:accion`) que el rol concede. */
143
+ permissions: string[];
144
+ }
145
+ export interface CatalogSpec {
146
+ /** Todos los permisos del catálogo (formato `recurso:accion`). */
147
+ permissions: Array<{
148
+ slug: string;
149
+ description?: string | null;
150
+ }>;
151
+ roles: CatalogRoleSpec[];
152
+ }
153
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Contrato del sistema de autorización del chasis (puerto + drivers).
3
+ *
4
+ * El chasis NO condena a un backend concreto: todo call-site (middleware,
5
+ * services, seeders) habla con este contrato a través del manager
6
+ * (`#services/authorization/main`). El driver `database` (motor propio sobre
7
+ * las tablas `authz_*`) es el default autosuficiente; un driver `openfga` u
8
+ * otro custom se registra en `config/authorization.ts` sin tocar call-sites.
9
+ *
10
+ * ── Semántica que TODO driver debe respetar ──────────────────────────────
11
+ * La verifica `tests/contracts/authorization_driver_contract.ts` (la misma
12
+ * suite corre contra cada driver — es el juez del contrato):
13
+ *
14
+ * 1. **Scopes jerárquicos, herencia SOLO hacia abajo.** La cadena de un scope
15
+ * es `[scope, ...ancestros]` (`app` es la raíz: su cadena es él mismo).
16
+ * Un grant en un scope autoriza en ese scope y en TODOS sus descendientes;
17
+ * nunca en hermanos ni ancestros. En T1 solo opera `app` (los ancestros de
18
+ * `organization`/`unit` se completan en T2/T3 vía `resolveAncestors`).
19
+ * 2. **Deny explícito gana.** Un deny de un permiso en cualquier scope de la
20
+ * cadena bloquea `authorize`, aunque un rol lo conceda (el deny también
21
+ * hereda hacia abajo). Quitar el deny restaura el permiso.
22
+ * 3. **Expiración observable.** Una asignación con `expiresAt` en el pasado
23
+ * no concede nada; con `expiresAt` futuro concede normalmente.
24
+ * 4. **Holder polimórfico.** `SubjectRef.type` es el morph name del modelo
25
+ * (`users` | `admins` | `integrations` | los del consumidor). Dos holders
26
+ * con el mismo uuid y distinto type JAMÁS se cruzan.
27
+ * 5. **Denegación por defecto.** Permiso desconocido, rol sin el permiso o
28
+ * holder sin asignación vigente → `false`, nunca throw en `authorize`.
29
+ * En cambio `grant`/`deny` con rol/permiso fuera del catálogo → throw
30
+ * (error de programación, no de autorización).
31
+ * 6. **Idempotencia de escritura.** Re-`grant` no duplica (actualiza
32
+ * `expiresAt`); re-`revoke`/re-`deny`/re-`removeDeny` son no-ops seguros.
33
+ */
34
+ /** Nombre reservado del scope raíz. */
35
+ export const APP_SCOPE_TYPE = 'app';
36
+ /** El scope raíz de aplicación (nivel plataforma). */
37
+ export const APP_SCOPE = Object.freeze({ type: 'app', uuid: null });
38
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAoBH,uCAAuC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAA;AAQnC,sDAAsD;AACtD,MAAM,CAAC,MAAM,SAAS,GAAa,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA"}
@@ -0,0 +1,81 @@
1
+ {{{
2
+ exports({ to: app.configPath('app_acl.ts') })
3
+ }}}
4
+ import type { CatalogSpec } from '@jantstack/adonis-authz'
5
+
6
+ /**
7
+ * Catálogo del ACL de NIVEL APLICACIÓN (scope `app` del motor de
8
+ * autorización propio). Single source of truth de roles/permisos de
9
+ * plataforma: lo sincroniza `database/seeder_source/app_acl_seeder.ts`
10
+ * (idempotente y aditivo, mismo contrato que organization_acl).
11
+ *
12
+ * Gramática unificada con las abilities de tokens (M3): los slugs usan
13
+ * `recurso:accion` y se registran en el registry de abilities
14
+ * (`start/authz.ts`) — un token delegado puede acotar EXACTAMENTE con los
15
+ * mismos nombres que el ACL concede.
16
+ *
17
+ * Para el ACL POR TENANT ver `config/organization_acl.ts` (migra al motor
18
+ * en la tanda 2).
19
+ *
20
+ * Workflow para añadir un permiso:
21
+ * 1. Editar este archivo.
22
+ * 2. `node ace db:seed:one app_acl_seeder`
23
+ */
24
+ const appAclConfig = {
25
+ /**
26
+ * Permisos de plataforma del chasis. El derivado añade los suyos aquí
27
+ * (formato `recurso:accion` en minúsculas).
28
+ */
29
+ permissions: [
30
+ { slug: 'audit:read', description: 'Leer el log de auditoría global de la plataforma' },
31
+ { slug: 'admin:manage', description: 'Gestionar admins y sus roles de plataforma' },
32
+ { slug: 'organizations:read', description: 'Leer cualquier organization de la plataforma' },
33
+ ],
34
+
35
+ /**
36
+ * Roles asignables a nivel app (típicamente a holders del guard admins).
37
+ * UUIDs fijos: mismo uuid en todos los entornos (patrón organization_acl).
38
+ * `permissions: '*'` = todos los permisos del catálogo.
39
+ */
40
+ roles: [
41
+ {
42
+ uuid: '019da000-0002-7000-8000-000000000001',
43
+ slug: 'superadmin',
44
+ name: 'Superadmin',
45
+ description: 'Acceso total al plano de administración de la plataforma.',
46
+ rank: 100,
47
+ permissions: '*' as const,
48
+ },
49
+ {
50
+ uuid: '019da000-0002-7000-8000-000000000002',
51
+ slug: 'support',
52
+ name: 'Support',
53
+ description: 'Soporte: lectura de auditoría y organizations, sin gestión de admins.',
54
+ rank: 50,
55
+ permissions: ['audit:read', 'organizations:read'],
56
+ },
57
+ ],
58
+ }
59
+
60
+ /** Slugs de permisos del nivel app (se registran como abilities — M3). */
61
+ export function appPermissionSlugs(): string[] {
62
+ return appAclConfig.permissions.map((p) => p.slug)
63
+ }
64
+
65
+ /** El catálogo en el formato del motor (`syncAuthzCatalog`). */
66
+ export function appAclCatalog(): CatalogSpec {
67
+ return {
68
+ permissions: appAclConfig.permissions,
69
+ roles: appAclConfig.roles.map((role) => ({
70
+ uuid: role.uuid,
71
+ slug: role.slug,
72
+ scopeType: 'app',
73
+ name: role.name,
74
+ description: role.description,
75
+ rank: role.rank,
76
+ permissions: role.permissions === '*' ? appPermissionSlugs() : role.permissions,
77
+ })),
78
+ }
79
+ }
80
+
81
+ export default appAclConfig
@@ -0,0 +1,74 @@
1
+ {{{
2
+ exports({ to: app.configPath('authorization.ts') })
3
+ }}}
4
+ import env from '#start/env'
5
+ import { defineConfig, DatabaseAuthorizationDriver } from '@jantstack/adonis-authz'
6
+ import type { AuthzWriteEvent, ScopeRef } from '@jantstack/adonis-authz'
7
+
8
+ /**
9
+ * Holders de tu aplicación: morph name (`@MorphMap` del modelo) → tipo del
10
+ * modelo FGA. Solo lo usa el driver `openfga` y sus comandos.
11
+ *
12
+ * ⚠️ Cambiar este mapa cambia el authorization model: hay que re-provisionar
13
+ * el store (`node ace openfga:provision`) y reimportar los hechos.
14
+ */
15
+ export const holderTypes = {
16
+ users: 'user',
17
+ }
18
+
19
+ /**
20
+ * Jerarquía de scopes de tu dominio. El motor solo conoce la raíz (`app`);
21
+ * si tienes niveles propios (organizaciones, proyectos, sedes…), devuelve
22
+ * aquí sus ancestros del más cercano a la raíz.
23
+ *
24
+ * organization → [APP_SCOPE]
25
+ * unit → [padres…, su organization, APP_SCOPE]
26
+ */
27
+ async function resolveScopeAncestors(scope: ScopeRef): Promise<ScopeRef[]> {
28
+ if (scope.type === 'app') return []
29
+ return [{ type: 'app', uuid: null }]
30
+ }
31
+
32
+ /**
33
+ * Side-effects de cada escritura del motor (grant/revoke/deny). El sitio
34
+ * natural para auditar. Debe ser best-effort: no lances desde aquí.
35
+ */
36
+ async function onAuthzWrite(_event: AuthzWriteEvent) {}
37
+
38
+ export default defineConfig({
39
+ default: env.get('AUTHZ_DRIVER', 'database'),
40
+
41
+ holderTypes,
42
+
43
+ openfga: {
44
+ url: env.get('OPENFGA_URL'),
45
+ storeId: env.get('OPENFGA_STORE_ID'),
46
+ modelId: env.get('OPENFGA_MODEL_ID'),
47
+ },
48
+
49
+ drivers: {
50
+ database: () => new DatabaseAuthorizationDriver({ resolveAncestors: resolveScopeAncestors }),
51
+
52
+ /**
53
+ * Backend externo opcional. Levanta el servidor y provisiona con
54
+ * `node ace openfga:provision`; migra los hechos con `openfga:import`.
55
+ */
56
+ openfga: async () => {
57
+ const { OpenFgaAuthorizationDriver } = await import('@jantstack/adonis-authz')
58
+ const apiUrl = env.get('OPENFGA_URL')
59
+ const storeId = env.get('OPENFGA_STORE_ID')
60
+ if (!apiUrl || !storeId) {
61
+ throw new Error('AUTHZ_DRIVER=openfga requiere OPENFGA_URL y OPENFGA_STORE_ID')
62
+ }
63
+ return new OpenFgaAuthorizationDriver({
64
+ apiUrl,
65
+ storeId,
66
+ modelId: env.get('OPENFGA_MODEL_ID'),
67
+ resolveAncestors: resolveScopeAncestors,
68
+ holderTypes,
69
+ })
70
+ },
71
+ },
72
+
73
+ hooks: { onWrite: onAuthzWrite },
74
+ })
@@ -0,0 +1,3 @@
1
+ /** Raíz de los stubs publicables por `configure`. */
2
+ export declare const stubsRoot: string;
3
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../stubs/main.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,eAAO,MAAM,SAAS,QAAsB,CAAA"}
@@ -0,0 +1,3 @@
1
+ /** Raíz de los stubs publicables por `configure`. */
2
+ export const stubsRoot = import.meta.dirname;
3
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../stubs/main.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAA"}