shutro-erp 0.3.2 → 0.3.4

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 (156) hide show
  1. package/dist/account_portal/.kosh/bindings.js +1 -1
  2. package/dist/account_portal/.kosh/schema.d.ts +156 -1
  3. package/dist/accounting/.kosh/bindings.js +1 -1
  4. package/dist/accounting/.kosh/schema.d.ts +156 -1
  5. package/dist/assistant/index.js +1 -1
  6. package/dist/contacts/.kosh/bindings.js +1 -1
  7. package/dist/contacts/.kosh/schema.d.ts +156 -1
  8. package/dist/integrations/index.js +12 -0
  9. package/dist/integrations/web/OAuthAppsPage.d.ts +9 -0
  10. package/dist/integrations/web/OAuthAppsPage.js +79 -0
  11. package/dist/integrations/web/index.d.ts +1 -0
  12. package/dist/integrations/web/index.js +3 -0
  13. package/dist/integrations/web/messages.js +58 -0
  14. package/dist/l10n_bd/.kosh/bindings.js +1 -1
  15. package/dist/l10n_bd/.kosh/schema.d.ts +156 -1
  16. package/dist/l10n_in/.kosh/bindings.js +1 -1
  17. package/dist/l10n_in/.kosh/schema.d.ts +156 -4
  18. package/dist/l10n_in/module.d.ts +0 -62
  19. package/dist/l10n_in/module.js +2 -4
  20. package/dist/messaging/web/index.js +1 -1
  21. package/dist/notify/web/index.js +1 -1
  22. package/dist/payment/.kosh/bindings.js +1 -1
  23. package/dist/payment/.kosh/schema.d.ts +157 -2
  24. package/dist/payment/bkash.d.ts +28 -0
  25. package/dist/payment/bkash.js +169 -0
  26. package/dist/payment/index.d.ts +4 -0
  27. package/dist/payment/index.js +80 -24
  28. package/dist/payment/module.d.ts +7 -4
  29. package/dist/payment/module.js +3 -0
  30. package/dist/payment/money.d.ts +7 -0
  31. package/dist/payment/money.js +37 -0
  32. package/dist/payment/providers.d.ts +13 -2
  33. package/dist/payment/razorpay.d.ts +12 -0
  34. package/dist/payment/razorpay.js +149 -0
  35. package/dist/payment/sslcommerz.js +1 -1
  36. package/dist/payment/stripe.d.ts +15 -0
  37. package/dist/payment/stripe.js +182 -0
  38. package/dist/permissions/admin.d.ts +3 -0
  39. package/dist/permissions/admin.js +108 -10
  40. package/dist/permissions/index.d.ts +1 -0
  41. package/dist/permissions/index.js +3 -0
  42. package/dist/permissions/roles.d.ts +2 -0
  43. package/dist/permissions/roles.js +236 -0
  44. package/dist/portal/.kosh/bindings.js +1 -1
  45. package/dist/portal/.kosh/schema.d.ts +156 -1
  46. package/dist/product/.kosh/bindings.js +1 -1
  47. package/dist/product/.kosh/schema.d.ts +156 -1
  48. package/dist/project/.kosh/bindings.js +1 -1
  49. package/dist/project/.kosh/schema.d.ts +156 -1
  50. package/dist/project_portal/.kosh/bindings.js +1 -1
  51. package/dist/project_portal/.kosh/schema.d.ts +156 -1
  52. package/dist/purchase/.kosh/bindings.js +1 -1
  53. package/dist/purchase/.kosh/schema.d.ts +156 -1
  54. package/dist/purchase_account/.kosh/bindings.js +1 -1
  55. package/dist/purchase_account/.kosh/schema.d.ts +156 -1
  56. package/dist/purchase_portal/.kosh/bindings.js +1 -1
  57. package/dist/purchase_portal/.kosh/schema.d.ts +156 -1
  58. package/dist/sale_account/.kosh/bindings.js +1 -1
  59. package/dist/sale_account/.kosh/schema.d.ts +156 -1
  60. package/dist/sale_portal/.kosh/bindings.js +1 -1
  61. package/dist/sale_portal/.kosh/schema.d.ts +156 -1
  62. package/dist/sale_project/.kosh/bindings.js +1 -1
  63. package/dist/sale_project/.kosh/schema.d.ts +156 -1
  64. package/dist/sales/.kosh/bindings.js +1 -1
  65. package/dist/sales/.kosh/schema.d.ts +156 -1
  66. package/dist/server/auth/base.js +98 -0
  67. package/dist/server/auth/oauth.d.ts +21 -0
  68. package/dist/server/auth/oauth.js +579 -0
  69. package/dist/server/auth/routes.d.ts +3 -0
  70. package/dist/server/auth/routes.js +29 -0
  71. package/dist/server/auth/service.d.ts +56 -0
  72. package/dist/server/auth/service.js +185 -3
  73. package/dist/server/identity.d.ts +4 -0
  74. package/dist/server/images.d.ts +12 -0
  75. package/dist/server/images.js +139 -0
  76. package/dist/server/index.d.ts +2 -1
  77. package/dist/server/index.js +1 -0
  78. package/dist/server/server.d.ts +4 -0
  79. package/dist/server/server.js +20 -4
  80. package/dist/settings/company.d.ts +34 -0
  81. package/dist/settings/company.js +189 -0
  82. package/dist/settings/index.d.ts +10 -10
  83. package/dist/settings/index.js +159 -30
  84. package/dist/settings/people.d.ts +16 -0
  85. package/dist/settings/people.js +507 -0
  86. package/dist/settings/security.d.ts +13 -0
  87. package/dist/settings/security.js +158 -0
  88. package/dist/settings/web/AuditPage.d.ts +8 -0
  89. package/dist/settings/web/AuditPage.js +74 -0
  90. package/dist/settings/web/CompaniesPage.d.ts +8 -0
  91. package/dist/settings/web/CompaniesPage.js +52 -0
  92. package/dist/settings/web/CompanyPage.d.ts +9 -0
  93. package/dist/settings/web/CompanyPage.js +105 -0
  94. package/dist/settings/web/ConnectedAppsPage.d.ts +7 -0
  95. package/dist/settings/web/ConnectedAppsPage.js +33 -0
  96. package/dist/settings/web/OverviewPage.d.ts +9 -0
  97. package/dist/settings/web/OverviewPage.js +77 -0
  98. package/dist/settings/web/PeoplePage.d.ts +9 -0
  99. package/dist/settings/web/PeoplePage.js +154 -0
  100. package/dist/settings/web/ProfilePage.d.ts +14 -0
  101. package/dist/settings/web/ProfilePage.js +196 -0
  102. package/dist/settings/web/RolesEditor.d.ts +35 -0
  103. package/dist/settings/web/RolesEditor.js +49 -0
  104. package/dist/settings/web/RolesPage.d.ts +9 -0
  105. package/dist/settings/web/RolesPage.js +296 -0
  106. package/dist/settings/web/SecurityPage.d.ts +8 -0
  107. package/dist/settings/web/SecurityPage.js +81 -0
  108. package/dist/settings/web/index.d.ts +10 -0
  109. package/dist/settings/web/index.js +31 -1
  110. package/dist/settings/web/messages.js +594 -0
  111. package/dist/ui/api.d.ts +8 -0
  112. package/dist/ui/app.d.ts +5 -0
  113. package/dist/ui/app.js +143 -33
  114. package/dist/ui/components/AppIcon.js +11 -1
  115. package/dist/ui/components/Avatar.d.ts +21 -0
  116. package/dist/ui/components/Avatar.js +71 -0
  117. package/dist/ui/components/primitives.d.ts +9 -1
  118. package/dist/ui/components/primitives.js +12 -4
  119. package/dist/ui/context.d.ts +10 -1
  120. package/dist/ui/context.js +60 -2
  121. package/dist/ui/i18n/messages.d.ts +76 -0
  122. package/dist/ui/i18n/messages.js +152 -0
  123. package/dist/ui/index.d.ts +3 -1
  124. package/dist/ui/index.js +3 -1
  125. package/dist/ui/lib/accent.d.ts +13 -0
  126. package/dist/ui/lib/accent.js +36 -0
  127. package/dist/ui/registry.d.ts +7 -1
  128. package/dist/ui/registry.js +10 -1
  129. package/dist/ui/search/ViewTabs.d.ts +14 -0
  130. package/dist/ui/search/ViewTabs.js +42 -0
  131. package/dist/ui/shell/Activate.d.ts +6 -0
  132. package/dist/ui/shell/Activate.js +39 -0
  133. package/dist/ui/shell/CommandPalette.d.ts +7 -1
  134. package/dist/ui/shell/CommandPalette.js +16 -2
  135. package/dist/ui/shell/Consent.d.ts +5 -0
  136. package/dist/ui/shell/Consent.js +35 -0
  137. package/dist/ui/shell/Home.js +85 -16
  138. package/dist/ui/shell/Sidebar.d.ts +27 -0
  139. package/dist/ui/shell/Sidebar.js +77 -0
  140. package/dist/ui/shell/TwoFactorSetup.d.ts +5 -0
  141. package/dist/ui/shell/TwoFactorSetup.js +32 -0
  142. package/dist/ui/shell/shortcuts.d.ts +3 -0
  143. package/dist/ui/shell/shortcuts.js +13 -4
  144. package/dist/ui/styles.css +70 -28
  145. package/dist/ui/views/DateField.d.ts +10 -0
  146. package/dist/ui/views/DateField.js +129 -0
  147. package/dist/ui/views/FormView.js +161 -21
  148. package/dist/ui/views/ListView.d.ts +2 -0
  149. package/dist/ui/views/ListView.js +57 -25
  150. package/dist/ui/views/StatusChip.d.ts +10 -0
  151. package/dist/ui/views/StatusChip.js +22 -0
  152. package/dist/ui/views/widgets.d.ts +3 -0
  153. package/dist/ui/views/widgets.js +26 -8
  154. package/dist/views/types.d.ts +7 -0
  155. package/dist/views/validate.js +4 -0
  156. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 698d6a45d2c40df8
1
+ // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 7dbe00f1ac846381
2
2
  // Schema view of module `sale_project` (RFC 0002 §7.7): the models it owns or depends on, with the extensions it can see.
3
3
  import type { F } from '../../server/orm.js';
4
4
 
@@ -8,9 +8,11 @@ export interface SchemaView {
8
8
  readonly 'audit.event': AuditEvent;
9
9
  readonly 'auth.api_key': AuthApiKey;
10
10
  readonly 'auth.credential': AuthCredential;
11
+ readonly 'auth.policy': AuthPolicy;
11
12
  readonly 'auth.session': AuthSession;
12
13
  readonly 'auth.user_grant': AuthUserGrant;
13
14
  readonly 'auth.user_group': AuthUserGroup;
15
+ readonly 'kosh.image': KoshImage;
14
16
  readonly 'kosh.saved_view': KoshSavedView;
15
17
  readonly 'mail.activity': MailActivity;
16
18
  readonly 'mail.activity.type': MailActivityType;
@@ -19,6 +21,10 @@ export interface SchemaView {
19
21
  readonly 'mail.follower': MailFollower;
20
22
  readonly 'mail.message': MailMessage;
21
23
  readonly 'mail.message.reaction': MailMessageReaction;
24
+ readonly 'oauth.app': OauthApp;
25
+ readonly 'oauth.code': OauthCode;
26
+ readonly 'oauth.grant': OauthGrant;
27
+ readonly 'oauth.token': OauthToken;
22
28
  readonly 'product.category': ProductCategory;
23
29
  readonly 'product.product': ProductProduct;
24
30
  readonly 'project.project': ProjectProject;
@@ -140,6 +146,26 @@ export interface AuthCredential {
140
146
  export interface AuthCredentialMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.credential'> {
141
147
  }
142
148
 
149
+ /** `auth.policy` (owner: base). */
150
+ export interface AuthPolicy {
151
+ readonly name: 'auth.policy';
152
+ readonly fields: {
153
+ readonly id: F.Id<'auth.policy'>;
154
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
155
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
156
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
157
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
158
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
159
+ readonly twoFactor: F.Selection<'administrators' | 'everyone', { readonly required: true; readonly default: true }>;
160
+ readonly sessionDays: F.Integer;
161
+ };
162
+ readonly methods: AuthPolicyMethods;
163
+ }
164
+
165
+ /** Methods of `auth.policy`: declared ones and transitions. */
166
+ export interface AuthPolicyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.policy'> {
167
+ }
168
+
143
169
  /** `auth.session` (owner: base). */
144
170
  export interface AuthSession {
145
171
  readonly name: 'auth.session';
@@ -212,6 +238,29 @@ export interface AuthUserGroup {
212
238
  export interface AuthUserGroupMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.user_group'> {
213
239
  }
214
240
 
241
+ /** `kosh.image` (owner: base). */
242
+ export interface KoshImage {
243
+ readonly name: 'kosh.image';
244
+ readonly fields: {
245
+ readonly id: F.Id<'kosh.image'>;
246
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
247
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
248
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
249
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
250
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
251
+ readonly ownerModel: F.Char<{ readonly required: true }>;
252
+ readonly ownerId: F.Integer<{ readonly required: true }>;
253
+ readonly mime: F.Char<{ readonly required: true }>;
254
+ readonly data: F.Text<{ readonly required: true }>;
255
+ readonly hash: F.Char<{ readonly required: true }>;
256
+ };
257
+ readonly methods: KoshImageMethods;
258
+ }
259
+
260
+ /** Methods of `kosh.image`: declared ones and transitions. */
261
+ export interface KoshImageMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'kosh.image'> {
262
+ }
263
+
215
264
  /** `kosh.saved_view` (owner: base). */
216
265
  export interface KoshSavedView {
217
266
  readonly name: 'kosh.saved_view';
@@ -414,6 +463,105 @@ export interface MailMessageReaction {
414
463
  export interface MailMessageReactionMethods extends F.Methods<typeof import('../../messaging/index.js').messagingShutro, 'mail.message.reaction'> {
415
464
  }
416
465
 
466
+ /** `oauth.app` (owner: base). */
467
+ export interface OauthApp {
468
+ readonly name: 'oauth.app';
469
+ readonly fields: {
470
+ readonly id: F.Id<'oauth.app'>;
471
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
472
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
473
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
474
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
475
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
476
+ readonly name: F.Char<{ readonly required: true }>;
477
+ readonly clientId: F.Char<{ readonly required: true }>;
478
+ readonly secretHash: F.Char;
479
+ readonly confidential: F.Bool<{ readonly required: true; readonly default: true }>;
480
+ readonly redirectUris: F.Text<{ readonly required: true }>;
481
+ readonly scopes: F.Char<{ readonly required: true }>;
482
+ readonly homepage: F.Char;
483
+ readonly active: F.Bool<{ readonly required: true; readonly default: true }>;
484
+ readonly owner: F.Many2one<'res.users'>;
485
+ };
486
+ readonly methods: OauthAppMethods;
487
+ }
488
+
489
+ /** Methods of `oauth.app`: declared ones and transitions. */
490
+ export interface OauthAppMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.app'> {
491
+ }
492
+
493
+ /** `oauth.code` (owner: base). */
494
+ export interface OauthCode {
495
+ readonly name: 'oauth.code';
496
+ readonly fields: {
497
+ readonly id: F.Id<'oauth.code'>;
498
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
499
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
500
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
501
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
502
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
503
+ readonly codeHash: F.Char<{ readonly required: true }>;
504
+ readonly grant: F.Many2one<'oauth.grant', { readonly required: true }>;
505
+ readonly redirectUri: F.Char<{ readonly required: true }>;
506
+ readonly challenge: F.Char;
507
+ readonly expiresAt: F.Datetime<{ readonly required: true }>;
508
+ readonly used: F.Bool<{ readonly required: true; readonly default: true }>;
509
+ };
510
+ readonly methods: OauthCodeMethods;
511
+ }
512
+
513
+ /** Methods of `oauth.code`: declared ones and transitions. */
514
+ export interface OauthCodeMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.code'> {
515
+ }
516
+
517
+ /** `oauth.grant` (owner: base). */
518
+ export interface OauthGrant {
519
+ readonly name: 'oauth.grant';
520
+ readonly fields: {
521
+ readonly id: F.Id<'oauth.grant'>;
522
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
523
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
524
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
525
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
526
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
527
+ readonly user: F.Many2one<'res.users', { readonly required: true }>;
528
+ readonly app: F.Many2one<'oauth.app', { readonly required: true }>;
529
+ readonly scopes: F.Char<{ readonly required: true }>;
530
+ readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
531
+ readonly lastUsedAt: F.Datetime;
532
+ };
533
+ readonly methods: OauthGrantMethods;
534
+ }
535
+
536
+ /** Methods of `oauth.grant`: declared ones and transitions. */
537
+ export interface OauthGrantMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.grant'> {
538
+ }
539
+
540
+ /** `oauth.token` (owner: base). */
541
+ export interface OauthToken {
542
+ readonly name: 'oauth.token';
543
+ readonly fields: {
544
+ readonly id: F.Id<'oauth.token'>;
545
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
546
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
547
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
548
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
549
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
550
+ readonly grant: F.Many2one<'oauth.grant', { readonly required: true }>;
551
+ readonly accessHash: F.Char<{ readonly required: true }>;
552
+ readonly refreshHash: F.Char<{ readonly required: true }>;
553
+ readonly accessExpiresAt: F.Datetime<{ readonly required: true }>;
554
+ readonly refreshExpiresAt: F.Datetime<{ readonly required: true }>;
555
+ readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
556
+ readonly rotated: F.Bool<{ readonly required: true; readonly default: true }>;
557
+ };
558
+ readonly methods: OauthTokenMethods;
559
+ }
560
+
561
+ /** Methods of `oauth.token`: declared ones and transitions. */
562
+ export interface OauthTokenMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.token'> {
563
+ }
564
+
417
565
  /** `product.category` (owner: product). */
418
566
  export interface ProductCategory {
419
567
  readonly name: 'product.category';
@@ -596,6 +744,13 @@ export interface ResCompany {
596
744
  readonly name: F.Char<{ readonly required: true }>;
597
745
  readonly currency: F.Many2one<'res.currency', { readonly required: true }>;
598
746
  readonly numberGrouping: F.Selection<'international' | 'lakh', { readonly required: true; readonly default: true }>;
747
+ readonly accentColor: F.Char;
748
+ readonly street: F.Char;
749
+ readonly city: F.Char;
750
+ readonly zip: F.Char;
751
+ readonly email: F.Char;
752
+ readonly phone: F.Char;
753
+ readonly website: F.Char;
599
754
  };
600
755
  readonly methods: ResCompanyMethods;
601
756
  }
@@ -1,4 +1,4 @@
1
- // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: b513566045fc25a0
1
+ // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 680b65ef8ba5f90d
2
2
  // Bindings of module `sales`: import the definition API from here to get types scoped to what it can see.
3
3
  export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
4
4
  import { definitions } from '../../server/orm.js';
@@ -1,4 +1,4 @@
1
- // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: b513566045fc25a0
1
+ // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 680b65ef8ba5f90d
2
2
  // Schema view of module `sales` (RFC 0002 §7.7): the models it owns or depends on, with the extensions it can see.
3
3
  import type { F } from '../../server/orm.js';
4
4
 
@@ -8,9 +8,11 @@ export interface SchemaView {
8
8
  readonly 'audit.event': AuditEvent;
9
9
  readonly 'auth.api_key': AuthApiKey;
10
10
  readonly 'auth.credential': AuthCredential;
11
+ readonly 'auth.policy': AuthPolicy;
11
12
  readonly 'auth.session': AuthSession;
12
13
  readonly 'auth.user_grant': AuthUserGrant;
13
14
  readonly 'auth.user_group': AuthUserGroup;
15
+ readonly 'kosh.image': KoshImage;
14
16
  readonly 'kosh.saved_view': KoshSavedView;
15
17
  readonly 'mail.activity': MailActivity;
16
18
  readonly 'mail.activity.type': MailActivityType;
@@ -19,6 +21,10 @@ export interface SchemaView {
19
21
  readonly 'mail.follower': MailFollower;
20
22
  readonly 'mail.message': MailMessage;
21
23
  readonly 'mail.message.reaction': MailMessageReaction;
24
+ readonly 'oauth.app': OauthApp;
25
+ readonly 'oauth.code': OauthCode;
26
+ readonly 'oauth.grant': OauthGrant;
27
+ readonly 'oauth.token': OauthToken;
22
28
  readonly 'product.category': ProductCategory;
23
29
  readonly 'product.product': ProductProduct;
24
30
  readonly 'res.company': ResCompany;
@@ -136,6 +142,26 @@ export interface AuthCredential {
136
142
  export interface AuthCredentialMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.credential'> {
137
143
  }
138
144
 
145
+ /** `auth.policy` (owner: base). */
146
+ export interface AuthPolicy {
147
+ readonly name: 'auth.policy';
148
+ readonly fields: {
149
+ readonly id: F.Id<'auth.policy'>;
150
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
151
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
152
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
153
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
154
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
155
+ readonly twoFactor: F.Selection<'administrators' | 'everyone', { readonly required: true; readonly default: true }>;
156
+ readonly sessionDays: F.Integer;
157
+ };
158
+ readonly methods: AuthPolicyMethods;
159
+ }
160
+
161
+ /** Methods of `auth.policy`: declared ones and transitions. */
162
+ export interface AuthPolicyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.policy'> {
163
+ }
164
+
139
165
  /** `auth.session` (owner: base). */
140
166
  export interface AuthSession {
141
167
  readonly name: 'auth.session';
@@ -208,6 +234,29 @@ export interface AuthUserGroup {
208
234
  export interface AuthUserGroupMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'auth.user_group'> {
209
235
  }
210
236
 
237
+ /** `kosh.image` (owner: base). */
238
+ export interface KoshImage {
239
+ readonly name: 'kosh.image';
240
+ readonly fields: {
241
+ readonly id: F.Id<'kosh.image'>;
242
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
243
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
244
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
245
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
246
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
247
+ readonly ownerModel: F.Char<{ readonly required: true }>;
248
+ readonly ownerId: F.Integer<{ readonly required: true }>;
249
+ readonly mime: F.Char<{ readonly required: true }>;
250
+ readonly data: F.Text<{ readonly required: true }>;
251
+ readonly hash: F.Char<{ readonly required: true }>;
252
+ };
253
+ readonly methods: KoshImageMethods;
254
+ }
255
+
256
+ /** Methods of `kosh.image`: declared ones and transitions. */
257
+ export interface KoshImageMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'kosh.image'> {
258
+ }
259
+
211
260
  /** `kosh.saved_view` (owner: base). */
212
261
  export interface KoshSavedView {
213
262
  readonly name: 'kosh.saved_view';
@@ -410,6 +459,105 @@ export interface MailMessageReaction {
410
459
  export interface MailMessageReactionMethods extends F.Methods<typeof import('../../messaging/index.js').messagingShutro, 'mail.message.reaction'> {
411
460
  }
412
461
 
462
+ /** `oauth.app` (owner: base). */
463
+ export interface OauthApp {
464
+ readonly name: 'oauth.app';
465
+ readonly fields: {
466
+ readonly id: F.Id<'oauth.app'>;
467
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
468
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
469
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
470
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
471
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
472
+ readonly name: F.Char<{ readonly required: true }>;
473
+ readonly clientId: F.Char<{ readonly required: true }>;
474
+ readonly secretHash: F.Char;
475
+ readonly confidential: F.Bool<{ readonly required: true; readonly default: true }>;
476
+ readonly redirectUris: F.Text<{ readonly required: true }>;
477
+ readonly scopes: F.Char<{ readonly required: true }>;
478
+ readonly homepage: F.Char;
479
+ readonly active: F.Bool<{ readonly required: true; readonly default: true }>;
480
+ readonly owner: F.Many2one<'res.users'>;
481
+ };
482
+ readonly methods: OauthAppMethods;
483
+ }
484
+
485
+ /** Methods of `oauth.app`: declared ones and transitions. */
486
+ export interface OauthAppMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.app'> {
487
+ }
488
+
489
+ /** `oauth.code` (owner: base). */
490
+ export interface OauthCode {
491
+ readonly name: 'oauth.code';
492
+ readonly fields: {
493
+ readonly id: F.Id<'oauth.code'>;
494
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
495
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
496
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
497
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
498
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
499
+ readonly codeHash: F.Char<{ readonly required: true }>;
500
+ readonly grant: F.Many2one<'oauth.grant', { readonly required: true }>;
501
+ readonly redirectUri: F.Char<{ readonly required: true }>;
502
+ readonly challenge: F.Char;
503
+ readonly expiresAt: F.Datetime<{ readonly required: true }>;
504
+ readonly used: F.Bool<{ readonly required: true; readonly default: true }>;
505
+ };
506
+ readonly methods: OauthCodeMethods;
507
+ }
508
+
509
+ /** Methods of `oauth.code`: declared ones and transitions. */
510
+ export interface OauthCodeMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.code'> {
511
+ }
512
+
513
+ /** `oauth.grant` (owner: base). */
514
+ export interface OauthGrant {
515
+ readonly name: 'oauth.grant';
516
+ readonly fields: {
517
+ readonly id: F.Id<'oauth.grant'>;
518
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
519
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
520
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
521
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
522
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
523
+ readonly user: F.Many2one<'res.users', { readonly required: true }>;
524
+ readonly app: F.Many2one<'oauth.app', { readonly required: true }>;
525
+ readonly scopes: F.Char<{ readonly required: true }>;
526
+ readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
527
+ readonly lastUsedAt: F.Datetime;
528
+ };
529
+ readonly methods: OauthGrantMethods;
530
+ }
531
+
532
+ /** Methods of `oauth.grant`: declared ones and transitions. */
533
+ export interface OauthGrantMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.grant'> {
534
+ }
535
+
536
+ /** `oauth.token` (owner: base). */
537
+ export interface OauthToken {
538
+ readonly name: 'oauth.token';
539
+ readonly fields: {
540
+ readonly id: F.Id<'oauth.token'>;
541
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
542
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
543
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
544
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
545
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
546
+ readonly grant: F.Many2one<'oauth.grant', { readonly required: true }>;
547
+ readonly accessHash: F.Char<{ readonly required: true }>;
548
+ readonly refreshHash: F.Char<{ readonly required: true }>;
549
+ readonly accessExpiresAt: F.Datetime<{ readonly required: true }>;
550
+ readonly refreshExpiresAt: F.Datetime<{ readonly required: true }>;
551
+ readonly revoked: F.Bool<{ readonly required: true; readonly default: true }>;
552
+ readonly rotated: F.Bool<{ readonly required: true; readonly default: true }>;
553
+ };
554
+ readonly methods: OauthTokenMethods;
555
+ }
556
+
557
+ /** Methods of `oauth.token`: declared ones and transitions. */
558
+ export interface OauthTokenMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'oauth.token'> {
559
+ }
560
+
413
561
  /** `product.category` (owner: product). */
414
562
  export interface ProductCategory {
415
563
  readonly name: 'product.category';
@@ -477,6 +625,13 @@ export interface ResCompany {
477
625
  readonly name: F.Char<{ readonly required: true }>;
478
626
  readonly currency: F.Many2one<'res.currency', { readonly required: true }>;
479
627
  readonly numberGrouping: F.Selection<'international' | 'lakh', { readonly required: true; readonly default: true }>;
628
+ readonly accentColor: F.Char;
629
+ readonly street: F.Char;
630
+ readonly city: F.Char;
631
+ readonly zip: F.Char;
632
+ readonly email: F.Char;
633
+ readonly phone: F.Char;
634
+ readonly website: F.Char;
480
635
  };
481
636
  readonly methods: ResCompanyMethods;
482
637
  }
@@ -22,6 +22,15 @@ const ResCompany = defineModel('res.company', {
22
22
  currency: f.many2one('res.currency', { required: true }),
23
23
  /** How numbers are grouped on screen and in documents (RFC 0016): 1,234,567 or 12,34,567 (lakh and crore). */
24
24
  numberGrouping: f.selection({ international: 'International (1,234,567)', lakh: 'Lakh and crore (12,34,567)' }, { required: true, default: 'international', label: 'Number grouping' }),
25
+ /** The company's brand colour (`#4f46e5`), the back-office's accent (RFC 0018); the default when empty. */
26
+ accentColor: f.char({ size: 7, label: 'Brand colour' }),
27
+ /** Its address and how to reach it (RFC 0019 §3.4): on documents, e-invoices and the portal. */
28
+ street: f.char({ label: 'Address' }),
29
+ city: f.char({ label: 'City' }),
30
+ zip: f.char({ size: 12, label: 'Postal code' }),
31
+ email: f.char({ label: 'Email' }),
32
+ phone: f.char({ label: 'Phone' }),
33
+ website: f.char({ label: 'Website' }),
25
34
  },
26
35
  });
27
36
  const readRows = async (env, model, ids, keys) => env.asSuperuser({ reason: 'check administrators' }, async (su) => {
@@ -127,6 +136,83 @@ const AuthUserGrant = defineModel('auth.user_grant', {
127
136
  reason: f.char({ required: true }),
128
137
  },
129
138
  });
139
+ /**
140
+ * The installation's security policy (RFC 0019 §3.5): one row, read by the auth service, changed in Settings ›
141
+ * Security. Without a row: two-factor sign-in for administrators only, sessions as the server is configured.
142
+ */
143
+ const AuthPolicy = defineModel('auth.policy', {
144
+ fields: {
145
+ twoFactor: f.selection({ administrators: 'Administrators', everyone: 'Everyone' }, { required: true, default: 'administrators', label: 'Two-factor sign-in required for' }),
146
+ /** Days a sign-in lasts at most; empty: the server's setting. */
147
+ sessionDays: f.integer({ label: 'Session lifetime (days)' }),
148
+ },
149
+ });
150
+ /**
151
+ * OAuth 2.0 apps (RFC 0017 §5.2): third-party applications that act for a user who consented, within scopes. The
152
+ * client secret (confidential apps) is stored as a digest; public apps rely on PKCE. Private: managed by the
153
+ * Integrations routes and the OAuth flow.
154
+ */
155
+ const OAuthApp = defineModel('oauth.app', {
156
+ fields: {
157
+ name: f.char({ required: true }),
158
+ clientId: f.char({ required: true, index: 'unique' }),
159
+ secretHash: f.char(),
160
+ confidential: f.boolean({ default: true }),
161
+ /** One per line; the redirect must match one exactly. */
162
+ redirectUris: f.text({ required: true }),
163
+ /** The scopes it may ask for, space separated (`*`, `read:<app>`, `write:<app>`). */
164
+ scopes: f.char({ required: true }),
165
+ homepage: f.char(),
166
+ active: f.boolean({ default: true }),
167
+ owner: f.many2one('res.users', { ondelete: 'set null' }),
168
+ },
169
+ });
170
+ /** A user's consent to an app, with the scopes granted; revoking it ends every token of it. */
171
+ const OAuthGrant = defineModel('oauth.grant', {
172
+ fields: {
173
+ user: f.many2one('res.users', { required: true, ondelete: 'cascade' }),
174
+ app: f.many2one('oauth.app', { required: true, ondelete: 'cascade' }),
175
+ scopes: f.char({ required: true }),
176
+ revoked: f.boolean({ default: false }),
177
+ lastUsedAt: f.datetime(),
178
+ },
179
+ });
180
+ /** An authorization code: once, for 10 minutes, bound to its redirect and its PKCE challenge. */
181
+ const OAuthCode = defineModel('oauth.code', {
182
+ fields: {
183
+ codeHash: f.char({ required: true, index: 'unique' }),
184
+ grant: f.many2one('oauth.grant', { required: true, ondelete: 'cascade' }),
185
+ redirectUri: f.char({ required: true }),
186
+ challenge: f.char(),
187
+ expiresAt: f.datetime({ required: true }),
188
+ used: f.boolean({ default: false }),
189
+ },
190
+ });
191
+ /** An access token (1 hour) and its refresh token (rotated at each use), both stored as digests. */
192
+ const OAuthToken = defineModel('oauth.token', {
193
+ fields: {
194
+ grant: f.many2one('oauth.grant', { required: true, ondelete: 'cascade' }),
195
+ accessHash: f.char({ required: true, index: 'unique' }),
196
+ refreshHash: f.char({ required: true, index: 'unique' }),
197
+ accessExpiresAt: f.datetime({ required: true }),
198
+ refreshExpiresAt: f.datetime({ required: true }),
199
+ /** No longer valid: replaced by a newer pair, or revoked. */
200
+ revoked: f.boolean({ default: false }),
201
+ /** Replaced by a newer pair: its refresh token coming back means someone else holds it. */
202
+ rotated: f.boolean({ default: false }),
203
+ },
204
+ });
205
+ /** Profile photos and company logos (`images.ts`): small images, their bytes in base64. Private: served by routes. */
206
+ const KoshImage = defineModel('kosh.image', {
207
+ fields: {
208
+ ownerModel: f.char({ required: true, index: true }),
209
+ ownerId: f.integer({ required: true, index: true }),
210
+ mime: f.char({ required: true }),
211
+ data: f.text({ required: true }),
212
+ /** The bytes' digest (16 hex): the version in the image's URL. */
213
+ hash: f.char({ required: true }),
214
+ },
215
+ });
130
216
  /**
131
217
  * The security audit log (CLAUDE.md: logins, permission changes, exports, sensitive actions). Append-only: no one
132
218
  * may change or delete events (administrators included: the REST API never serves it, and the admin API only reads).
@@ -196,6 +282,12 @@ export const baseShutro = defineModule({
196
282
  AuthApiKey,
197
283
  AuthUserGroup,
198
284
  AuthUserGrant,
285
+ AuthPolicy,
286
+ OAuthApp,
287
+ OAuthGrant,
288
+ OAuthCode,
289
+ OAuthToken,
290
+ KoshImage,
199
291
  AuditEvent,
200
292
  SavedView,
201
293
  ],
@@ -214,6 +306,12 @@ export const base = defineKoshModule({
214
306
  'auth.api_key',
215
307
  'auth.user_group',
216
308
  'auth.user_grant',
309
+ 'auth.policy',
310
+ 'oauth.app',
311
+ 'oauth.grant',
312
+ 'oauth.code',
313
+ 'oauth.token',
314
+ 'kosh.image',
217
315
  'audit.event',
218
316
  ],
219
317
  });
@@ -0,0 +1,21 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { Env, Shutro } from '../orm.js';
3
+ import type { KoshRegistry } from '../registry.js';
4
+ import type { AuthService } from './service.js';
5
+ export declare const ACCESS_SECONDS = 3600;
6
+ /** Access tokens start with it: the server tells them from sessions and API keys at a glance. */
7
+ export declare const ACCESS_PREFIX = "oat_";
8
+ export interface OAuthOptions {
9
+ /** The back-office's address: the consent page is `<baseUrl>/oauth/authorize`. */
10
+ readonly baseUrl: string;
11
+ }
12
+ /** A resolved access token: who it acts as, within which scopes. */
13
+ export interface OAuthAccess {
14
+ readonly token: number;
15
+ readonly user: number;
16
+ readonly app: number;
17
+ readonly scopes: string[];
18
+ }
19
+ /** Finds the access token `token` (`oat_…`), live, of an active app and a grant not revoked. */
20
+ export declare function resolveAccessToken(env: Env, token: string): Promise<OAuthAccess | null>;
21
+ export declare function registerOAuthRoutes(app: FastifyInstance, auth: AuthService, shutro: () => Shutro, registry: KoshRegistry, options: OAuthOptions): void;