Serviced Account Mini Model¶
Purpose¶
This document is a developer-starting note for a bare-minimum Odoo Serviced Account model.
It does not attempt to finalize the full governance design. It exists to:
- capture why the problem is structurally non-trivial
- define a minimal object shape that can be prototyped in Odoo
- keep transactional Odoo behavior separate from governance behavior
- frame SSO and identity considerations without overloading the first model
1. Why This Is Not Straightforward¶
The Serviced Account object looks simple at first: "an organization that requires services."
But it quickly becomes more complex because:
- the same identity may act in multiple governance contexts
- internal and external organizations may both need governed access
- Odoo transaction structure, commercial boundaries, and delegated access do not perfectly align
- access may be mediated by a proxy API rather than native Odoo user seats
So the first model should be:
- flexible enough to represent real cases
- closed-boundary enough to avoid turning into a second CRM or HR system
- small enough to prototype and revise
2. Two Edge Cases That Motivate the Design¶
EC-001: Dual-Context Human Actor¶
The same person may appear as a single res.partner record, but participate in more than one governed context.
Example:
- the person is an employee/member inside an
OVACserviced account - the same person is also designated as account manager or sales-facing actor for an
EXTCserviced account
Why this matters:
- role meaning cannot safely live on
res.partneralone - authority must be carried by the relationship between person and serviced account
- permissions must stay isolated by account context
Design implication:
res.partneris the identity anchor- membership carries role, scope, and state
- authorization is evaluated in account context, never globally by person
EC-002: Cross-Company Conflict-of-Interest¶
Odoo is company-structured. Commercial boundaries matter.
Example:
- a person is modeled as member/employee under
OVAC / OV1 - the same person is proposed as designated account manager for
EXTCunderOV2 OV1andOV2are commercially distinct
This may be technically representable, but commercially sensitive.
Why this matters:
- the base model should not be so rigid that it forbids all mixed-role cases
- the base model should not be so loose that conflicts become invisible
Design implication:
- the structure should allow multi-context memberships
- conflict-of-interest checks should be handled by governance policy, not by over-hardcoding the schema
- sensitive cross-company combinations should be flaggable, reviewable, and auditable
3. Design Intent¶
The v0 model should answer only these questions:
- What organization is being governed?
- Which people may act in relation to it?
- Under which serviced-account context are they acting?
The v0 model should not try to solve:
- full enterprise RBAC
- complete internal org modeling
- advanced approval workflows
- full SSO implementation
- all conflict-of-interest policy combinations
4. Architectural Principles¶
4.1 Governance Is Not Transactions¶
All ERP business processes remain native Odoo:
- customers remain
res.partner - sales orders remain
sale.order - invoices remain
account.move - payments remain native accounting behavior
The ov.* domain is governance only.
This model does not:
- reimplement sales workflow
- reimplement pricing logic
- reimplement inventory
- duplicate customer master data
4.2 Separation of Concerns¶
| Domain | Responsibility |
|---|---|
res.partner |
Identity anchor for organizations and people |
| Odoo core models | Transaction and accounting truth |
ov.serviced_account |
Governed service-account tree |
ov.membership |
Authorization relationship in account context |
| Portal / UXI / BFF layer | Authentication and permission resolution |
| Proxy internal user | Technical execution of privileged actions |
4.3 Design Goals¶
- minimal schema surface
- deterministic, context-bound authorization
- hierarchy support without relying on
res.partner.parent_id - clean audit trail
- scope small enough to prototype and revise
5. Minimum Odoo Model Proposal¶
5.1 Core Objects¶
| Object | Purpose | Notes |
|---|---|---|
res.partner |
Identity anchor for organizations and people | Reuse Odoo native partner model; do not place contextual authority here |
ov.serviced_account |
Governed organization/account context | External client or eligible affiliated entity that receives governed service/access |
ov.membership |
Person-to-account authorization relationship | Carries role, state, and scope in account context |
5.2 ov.serviced_account Key Attributes¶
| Attribute | Type | Purpose | v0 Guidance |
|---|---|---|---|
name |
Char | Human-readable account name | Required |
partner_id |
Many2one(res.partner) |
Link to the canonical organization partner record | Required, unique in practice for v0 |
account_class |
Selection | Distinguish OVAC vs EXTC at minimum |
Required |
parent_id |
Many2one(ov.serviced_account) |
Optional hierarchy / branch structure | Optional |
child_ids |
One2many(ov.serviced_account) |
Convenience inverse for hierarchy | Derived |
state |
Selection | Governance lifecycle state | Start with active, inactive |
notes |
Text | Short admin/governance note | Optional, non-authoritative |
5.3 ov.membership Key Attributes¶
| Attribute | Type | Purpose | v0 Guidance |
|---|---|---|---|
serviced_account_id |
Many2one(ov.serviced_account) |
The governed account context | Required |
person_partner_id |
Many2one(res.partner) |
Person acting in that context | Required; person only |
role_code |
Char or Selection | Role in this account context | Keep simple in v0 |
membership_state |
Selection | Membership status | Start with active, suspended, revoked |
scope_policy |
Selection | Scope of authority | Start with this_node_only, this_node_and_descendants |
effective_from |
Datetime | Optional activation time | Optional |
effective_to |
Datetime | Optional expiry time | Optional |
5.4 Minimum Invariants¶
- A Serviced Account is an organization context, not a person.
- A person may have multiple memberships across multiple serviced accounts.
- Role semantics belong to
ov.membership, not directly tores.partner. - Transactional customer/order behavior remains native Odoo.
- Governance objects do not replace CRM, accounting, or company setup.
- Authorization is evaluated in account context, never by person alone.
5.5 Initial Role Pattern¶
Keep the initial role model simple.
Suggested v0 examples:
| Role | Example Capabilities |
|---|---|
admin |
full account management |
agent |
create draft sales orders or service actions |
finance |
view financial information and request invoice-related actions |
viewer |
read-only access |
Role logic should be enforced in the application and proxy/API layer, not hardcoded into native Odoo user-seat behavior.
6. What Counts As A Serviced Account In v0¶
For v0, a Serviced Account is:
- an organization that receives governed services, delegated access scope, or account-level operational governance
This may include:
EXTC- true external client/customer organizationOVAC- affiliated or subsidiary organization that still needs governed service/account treatment
This does not mean all Omnivoltaic internal org units should automatically be modeled as Serviced Accounts.
The working rule is:
- if the organization is being treated as an account subject of service/governance, it may be a Serviced Account
- if the organization is purely an internal operating structure, it should remain in normal Odoo company/org constructs unless a later need proves otherwise
7. SSO and Identity Considerations¶
The identity and access design must stay aligned with DIRAC architecture.
Relevant DIRAC prior disclosures:
- UXI is the single point of access with centralized authentication and authorization support
- FED is the enforcement layer for auth, entitlement, and role policies
- TEAMS is a Microsoft-based communications/document domain already relevant to OVES workflows
- DIRAC materials also reference SSO / Cloak-style authentication integration in the broader ecosystem
Implications for this mini-model:
- do not assume every governed actor will be a native paid Odoo user
- do not assume all identities originate inside Odoo CRM
- do not embed IdP-specific behavior directly into the first Odoo schema
Instead, separate:
- identity source: Teams / Microsoft-based identity, local portal identity, or other future IdP
- person anchor in Odoo:
res.partner - execution identity in Odoo: proxy/internal
res.users - governance authority:
ov.membership
7.1 Two Initial Identity Modes¶
| Mode | Likely Population | Identity Source | Odoo Pattern |
|---|---|---|---|
teams_federated |
OVAC-side users and other Microsoft-managed actors | Microsoft / Teams / Entra-style SSO path | Resolve external identity to res.partner, then evaluate ov.membership |
odoo_native_crm |
EXTC-side contacts/customers first known through CRM/commercial flows | Odoo-native partner/contact lifecycle, with later portal/SSO possible | Start from res.partner, then evaluate ov.membership |
7.2 What The Model Should Not Hardcode Yet¶
Do not hardcode in v0:
- Keycloak-specific tables or fields
- Microsoft tenant-specific claims mapping
- portal onboarding workflow
- automatic synchronization rules between Teams identities and Odoo users
Those belong to the next layer of identity/access design, not to the minimum Serviced Account object.
8. Proxy API Assumption¶
This mini-model assumes privileged Odoo actions may be executed by a proxy/internal user on behalf of non-seat actors.
Therefore:
- business actor attribution should not rely only on
create_uid - the account context used for access resolution should be explicit
- later implementation should add transaction-side attribution fields where needed
Examples of privileged actions that may go through the proxy path:
- confirm sales order
- create invoice
- issue refund
- edit account-affecting commercial controls
The important rule is:
- proxy
res.usersperforms technical execution - real human actor remains attributable separately
- serviced-account context remains explicit for audit and authorization
9. What We Are Not Building In v0¶
This model is intentionally not:
- a parallel customer model
- a replacement for native Odoo access rules
- a workflow engine
- a pricing or inventory abstraction
- a complete SSO implementation
- a full conflict-of-interest policy engine
10. Developer Starting Point¶
If developers start coding now, the first prototype should only prove:
- an organization partner can be wrapped by
ov.serviced_account - a person partner can hold multiple
ov.membershiprows - one person can appear in both
OVACandEXTCcontexts without schema breakage - role/scope live on membership, not on partner
- hierarchy is possible, but optional
11. Deferred By Design¶
Explicitly defer these items until after the first prototype:
- advanced role catalog
- supervisor model
- conflict-of-interest rule engine
- approval workflow engine
- detailed SSO mapper implementation
- transaction-side custom attribution fields beyond what is needed to prove the pattern
12. Guiding Principle¶
Keep the Serviced Account model:
- structural, not transactional
- contextual, not person-global
- flexible in relationships
- conservative in scope