Roles & Teams
The iam/ directory covers who may touch the data and who owns it. It maps to two schemas from the library's iam module: Role, for access levels and their approval chains, and TeamMember, for the people accountable for the contract.
Roles
Each access role is one Role value with an access level and its first- and second-level approvers. Writing them as separate named values means a role can be referenced from more than one contract without being retyped. This is iam/role.k:
import enkinex_odcs.iam.role
StrategyReader = role.Role {
role = "microstrategy_user_opr"
access = "read"
firstLevelApprovers = "Reporting Manager"
secondLevelApprovers = "mandolorian"
}
QueryReader = role.Role {
role = "bq_queryman_user_opr"
access = "read"
firstLevelApprovers = "Reporting Manager"
secondLevelApprovers = "na"
}
RiskReader = role.Role {
role = "risk_data_access_opr"
access = "read"
firstLevelApprovers = "Reporting Manager"
secondLevelApprovers = "dathvador"
}
BQWriter = role.Role {
role = "bq_unica_user_opr"
access = "write"
firstLevelApprovers = "Reporting Manager"
secondLevelApprovers = "mickey"
}
Team members
The people side lives in iam/member.k. Each is a TeamMember, and the fields carried differ per person — the first member records a dateOut and a replacedByUsername, the owner adds a description, and so on. The schema allows those optional fields without forcing them on every entry:
import enkinex_odcs.iam.team
CeastWoodMember = team.TeamMember {
username = "ceastwood"
role = "Data Scientist"
dateIn = "2022-08-02"
dateOut: "2022-10-01"
replacedByUsername = "mhopper"
}
MHopperMember = team.TeamMember {
username = "mhopper"
role = "Data Scientist"
dateIn = "2022-10-01"
}
DaustinMember = team.TeamMember {
username = "daustin"
role = "Owner"
description = "Keeper of the grail"
dateIn = "2022-10-01"
}
The individual members do not yet form a team. We assemble them into a Team back in odcs.k, which keeps the member definitions independent of how any one contract groups them.
Composing the root contract.k
Now we extend the root file from the previous section. Two new local imports appear — the iam modules — plus one library import, iam.team, because the Team wrapper is assembled inline. The team and roles fields join the ones we already had:
import enkinex_odcs.odcs
import enkinex_odcs.iam.team
import .contract.authoritative as contract_authoritative
import .contract.description as contract_description
import .contract.price as contract_price
import .contract.properties as contract_properties
import .contract.sla as contract_sla
import .contract.support as contract_support
import .iam.role as contract_role
import .iam.member as contract_member
odcs.DataContract {
domain = "seller"
version = "1.1.0"
status = "active"
id = "53581432-6c55-4ba2-a65f-72344a91553a"
tenant = "ClimateQuantumInc"
authoritativeDefinitions = [
contract_authoritative.SampleAuthoritativeDefinition
]
description = contract_description.SampleContractDescription
price = contract_price.MegabyteUSD
team = team.Team {
name = "my-team"
description = "The team owning the data contract"
members = [
contract_member.CeastWoodMember
contract_member.MHopperMember
contract_member.DaustinMember
]
}
roles = [
contract_role.StrategyReader
contract_role.QueryReader
contract_role.RiskReader
contract_role.BQWriter
]
slaProperties = [
contract_sla.LatencySla
contract_sla.GeneralAvailabilitySla
contract_sla.EndOfSupportSla
contract_sla.EndOfLifeSla
contract_sla.RetentionSla
contract_sla.FrequencySla
contract_sla.RegulatoryTimeOfAvailabilitySla
contract_sla.AnalyticsTimeOfAvailabilitySla
]
support = [
contract_support.SlackSupport
contract_support.EmailSupport
contract_support.FeedbackSupport
contract_support.TeamsSupport
]
tags = ["transactions"]
customProperties = [
contract_properties.RulesetProperty
contract_properties.SomeProperty
contract_properties.DataprocClusterProperty
]
contractCreatedTs = "2022-11-15T02:59:43+00:00"
}
The Team schema is the one place where we build a value inline in the root rather than in a leaf file, because the grouping — the team's own name and description — belongs to this contract, while the members it contains are reusable on their own. Everything else stays a reference to a named value.