Add Palam native contract for programmed transparency

Implement transparent ledger infrastructure for accountable governance:

- TransactionFlow tracking: Multi-party flows with complete audit trails
  - Full lifecycle: Initiation -> Intermediate steps -> Completion
  - Participant verification via Vita token (one-person-one-identity)
  - Immutable flow records with timestamp chains

- Encrypted Payload System: Role-based access to sensitive data
  - Payloads encrypted per-role (Consumer, Merchant, Bank, etc.)
  - Keys distributed to authorized parties only
  - Supports judicial declassification process

- Declassification Requests: Due process for accessing protected data
  - Judicial authority required (RolePalamJudge = 26)
  - Multi-party approval workflow
  - Configurable approval thresholds and expiry

- Audit Log System: Complete transparency for oversight
  - All operations logged with actor attribution
  - Auditor access via RolePalamAuditor (25)
  - Immutable chronological records

- Cross-contract integration:
  - Vita: Identity verification for participants
  - RoleRegistry: Role-based authorization
  - Lex: Rights enforcement for privacy protections

Latin naming: Palam = "openly/publicly" - reflecting the
contract's purpose of enabling transparent governance while
protecting legitimate privacy through programmed disclosure rules.

Contract ID: -23

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Tutus Development 2025-12-20 09:21:25 +00:00
parent 9a57598c91
commit 8ef02620ea
6 changed files with 1875 additions and 3 deletions

View File

@ -292,6 +292,17 @@ type (
// Address returns the contract's script hash.
Address() util.Uint160
}
// IPalam provides programmed transparency with role-based encrypted payloads.
IPalam interface {
interop.Contract
// GetFlowInternal returns a flow by ID.
GetFlowInternal(d *dao.Simple, flowID util.Uint256) *state.Flow
// HasDeclassifyGrant checks if requester has declassify grant for a flow.
HasDeclassifyGrant(d *dao.Simple, flowID util.Uint256, requester util.Uint160) bool
// Address returns the contract's script hash.
Address() util.Uint160
}
)
// Contracts is a convenient wrapper around an arbitrary set of native contracts
@ -479,6 +490,12 @@ func (cs *Contracts) Opus() IOpus {
return cs.ByName(nativenames.Opus).(IOpus)
}
// Palam returns native IPalam contract implementation. It panics if
// there's no contract with proper name in cs.
func (cs *Contracts) Palam() IPalam {
return cs.ByName(nativenames.Palam).(IPalam)
}
// NewDefaultContracts returns a new set of default native contracts.
func NewDefaultContracts(cfg config.ProtocolConfiguration) []interop.Contract {
mgmt := NewManagement()
@ -610,6 +627,13 @@ func NewDefaultContracts(cfg config.ProtocolConfiguration) []interop.Contract {
opus.Lex = lex
opus.Treasury = treasury
// Create Palam (Programmed Transparency) contract
palam := NewPalam()
palam.NEO = neo
palam.Vita = vita
palam.RoleRegistry = roleRegistry
palam.Lex = lex
return []interop.Contract{
mgmt,
s,
@ -633,5 +657,6 @@ func NewDefaultContracts(cfg config.ProtocolConfiguration) []interop.Contract {
sese,
tribute,
opus,
palam,
}
}

View File

@ -53,4 +53,6 @@ var (
Tribute = util.Uint160{0x35, 0x9b, 0xbf, 0x51, 0xb5, 0xe3, 0x73, 0x6d, 0x52, 0xad, 0x80, 0xb0, 0x28, 0x4f, 0x22, 0x8f, 0x9, 0xaf, 0x49, 0x1e}
// Opus is a hash of native Opus contract.
Opus = util.Uint160{0xf5, 0x22, 0x73, 0x17, 0x98, 0xab, 0xfc, 0x4d, 0x7c, 0x3a, 0x51, 0x8, 0x47, 0xc7, 0xe5, 0xe4, 0x6, 0x96, 0xb6, 0xfd}
// Palam is a hash of native Palam contract.
Palam = util.Uint160{0x3, 0x23, 0x73, 0xfa, 0x71, 0x3a, 0x34, 0xab, 0x8d, 0x8c, 0xfa, 0xe2, 0xb0, 0x46, 0xdf, 0x53, 0x88, 0x79, 0x16, 0xae}
)

View File

@ -51,4 +51,6 @@ const (
Tribute int32 = -21
// Opus is an ID of native Opus contract.
Opus int32 = -22
// Palam is an ID of native Palam contract.
Palam int32 = -23
)

View File

@ -24,6 +24,7 @@ const (
Sese = "Sese"
Tribute = "Tribute"
Opus = "Opus"
Palam = "Palam"
)
// All contains the list of all native contract names ordered by the contract ID.
@ -50,6 +51,7 @@ var All = []string{
Sese,
Tribute,
Opus,
Palam,
}
// IsValid checks if the name is a valid native contract's name.
@ -75,5 +77,6 @@ func IsValid(name string) bool {
name == Salus ||
name == Sese ||
name == Tribute ||
name == Opus
name == Opus ||
name == Palam
}

1127
pkg/core/native/palam.go Normal file

File diff suppressed because it is too large Load Diff

713
pkg/core/state/palam.go Normal file
View File

@ -0,0 +1,713 @@
package state
import (
"errors"
"math/big"
"github.com/tutus-one/tutus-chain/pkg/util"
"github.com/tutus-one/tutus-chain/pkg/vm/stackitem"
)
var errPalamInvalidStackItem = errors.New("invalid stack item")
// FlowStatus represents the status of a transaction flow.
type FlowStatus uint8
const (
FlowStatusActive FlowStatus = 0
FlowStatusArchived FlowStatus = 1
FlowStatusDisputed FlowStatus = 2
)
// DeclassifyStatus represents the status of a declassification request.
type DeclassifyStatus uint8
const (
DeclassifyPending DeclassifyStatus = 0
DeclassifyApproved DeclassifyStatus = 1
DeclassifyDenied DeclassifyStatus = 2
DeclassifyExpired DeclassifyStatus = 3
)
// PalamRole represents roles for transparency access.
type PalamRole uint8
const (
PalamRoleConsumer PalamRole = 0
PalamRoleMerchant PalamRole = 1
PalamRoleDistributor PalamRole = 2
PalamRoleProducer PalamRole = 3
PalamRoleNGO PalamRole = 4
PalamRoleAuditor PalamRole = 5
)
// AccessType represents types of data access.
type AccessType uint8
const (
AccessTypeView AccessType = 0
AccessTypeDeclassify AccessType = 1
AccessTypeAttach AccessType = 2
)
// Flow represents a transaction record with encrypted role-based payloads.
type Flow struct {
FlowID util.Uint256 // Unique identifier (hash of contents)
Bucket string // Time bucket (e.g., "2025-01-15T14:00:00Z")
Tag string // Category: COFFEE, DONATION, SUPPLY, etc.
Amount uint64 // Value in smallest unit
Timestamp uint32 // Block height when recorded
Creator util.Uint160 // Who created the flow
// Encrypted payloads - each role has its own encrypted view
ConsumerData []byte // Encrypted with Consumer key
MerchantData []byte // Encrypted with Merchant key
DistributorData []byte // Encrypted with Distributor key
ProducerData []byte // Encrypted with Producer key
NGOData []byte // Encrypted with NGO key
AuditorData []byte // Encrypted with Auditor key (requires declassify)
// Participants (script hashes)
Participants []util.Uint160
// Chain of custody
PreviousFlowID util.Uint256 // Links flows in a supply chain
Status FlowStatus
}
// ToStackItem converts Flow to a stack item.
func (f *Flow) ToStackItem() stackitem.Item {
participants := make([]stackitem.Item, len(f.Participants))
for i, p := range f.Participants {
participants[i] = stackitem.NewByteArray(p.BytesBE())
}
return stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray(f.FlowID.BytesBE()),
stackitem.NewByteArray([]byte(f.Bucket)),
stackitem.NewByteArray([]byte(f.Tag)),
stackitem.NewBigInteger(big.NewInt(int64(f.Amount))),
stackitem.NewBigInteger(big.NewInt(int64(f.Timestamp))),
stackitem.NewByteArray(f.Creator.BytesBE()),
stackitem.NewByteArray(f.ConsumerData),
stackitem.NewByteArray(f.MerchantData),
stackitem.NewByteArray(f.DistributorData),
stackitem.NewByteArray(f.ProducerData),
stackitem.NewByteArray(f.NGOData),
stackitem.NewByteArray(f.AuditorData),
stackitem.NewArray(participants),
stackitem.NewByteArray(f.PreviousFlowID.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(f.Status))),
})
}
// FromStackItem populates Flow from a stack item.
func (f *Flow) FromStackItem(item stackitem.Item) error {
arr, ok := item.Value().([]stackitem.Item)
if !ok || len(arr) < 15 {
return errPalamInvalidStackItem
}
flowIDBytes, err := arr[0].TryBytes()
if err != nil {
return err
}
f.FlowID, err = util.Uint256DecodeBytesBE(flowIDBytes)
if err != nil {
return err
}
bucketBytes, err := arr[1].TryBytes()
if err != nil {
return err
}
f.Bucket = string(bucketBytes)
tagBytes, err := arr[2].TryBytes()
if err != nil {
return err
}
f.Tag = string(tagBytes)
amount, err := arr[3].TryInteger()
if err != nil {
return err
}
f.Amount = amount.Uint64()
timestamp, err := arr[4].TryInteger()
if err != nil {
return err
}
f.Timestamp = uint32(timestamp.Uint64())
creatorBytes, err := arr[5].TryBytes()
if err != nil {
return err
}
f.Creator, err = util.Uint160DecodeBytesBE(creatorBytes)
if err != nil {
return err
}
f.ConsumerData, err = arr[6].TryBytes()
if err != nil {
return err
}
f.MerchantData, err = arr[7].TryBytes()
if err != nil {
return err
}
f.DistributorData, err = arr[8].TryBytes()
if err != nil {
return err
}
f.ProducerData, err = arr[9].TryBytes()
if err != nil {
return err
}
f.NGOData, err = arr[10].TryBytes()
if err != nil {
return err
}
f.AuditorData, err = arr[11].TryBytes()
if err != nil {
return err
}
participantsArr, ok := arr[12].Value().([]stackitem.Item)
if !ok {
return errPalamInvalidStackItem
}
f.Participants = make([]util.Uint160, len(participantsArr))
for i, p := range participantsArr {
pBytes, err := p.TryBytes()
if err != nil {
return err
}
f.Participants[i], err = util.Uint160DecodeBytesBE(pBytes)
if err != nil {
return err
}
}
prevFlowBytes, err := arr[13].TryBytes()
if err != nil {
return err
}
if len(prevFlowBytes) > 0 {
f.PreviousFlowID, err = util.Uint256DecodeBytesBE(prevFlowBytes)
if err != nil {
return err
}
}
status, err := arr[14].TryInteger()
if err != nil {
return err
}
f.Status = FlowStatus(status.Uint64())
return nil
}
// DeclassifyRequest represents a request for elevated access to flow data.
type DeclassifyRequest struct {
RequestID uint64 // Unique identifier
FlowID util.Uint256 // Target flow
CaseID string // Legal case reference
Reason string // Justification for access
Requester util.Uint160 // Script hash of requester
RequesterRole PalamRole // Must be Auditor
// Approval tracking
RequiredApprovals uint32 // e.g., 2 of 3
Approvals []util.Uint160 // Script hashes of approvers
ApprovalTimes []uint32 // Block heights of approvals
// Status
Status DeclassifyStatus
CreatedAt uint32 // Block height when created
ExpiresAt uint32 // Request expires if not approved
GrantedAt uint32 // When access was granted
}
// ToStackItem converts DeclassifyRequest to a stack item.
func (d *DeclassifyRequest) ToStackItem() stackitem.Item {
approvals := make([]stackitem.Item, len(d.Approvals))
for i, a := range d.Approvals {
approvals[i] = stackitem.NewByteArray(a.BytesBE())
}
approvalTimes := make([]stackitem.Item, len(d.ApprovalTimes))
for i, t := range d.ApprovalTimes {
approvalTimes[i] = stackitem.NewBigInteger(big.NewInt(int64(t)))
}
return stackitem.NewArray([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(d.RequestID))),
stackitem.NewByteArray(d.FlowID.BytesBE()),
stackitem.NewByteArray([]byte(d.CaseID)),
stackitem.NewByteArray([]byte(d.Reason)),
stackitem.NewByteArray(d.Requester.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(d.RequesterRole))),
stackitem.NewBigInteger(big.NewInt(int64(d.RequiredApprovals))),
stackitem.NewArray(approvals),
stackitem.NewArray(approvalTimes),
stackitem.NewBigInteger(big.NewInt(int64(d.Status))),
stackitem.NewBigInteger(big.NewInt(int64(d.CreatedAt))),
stackitem.NewBigInteger(big.NewInt(int64(d.ExpiresAt))),
stackitem.NewBigInteger(big.NewInt(int64(d.GrantedAt))),
})
}
// FromStackItem populates DeclassifyRequest from a stack item.
func (d *DeclassifyRequest) FromStackItem(item stackitem.Item) error {
arr, ok := item.Value().([]stackitem.Item)
if !ok || len(arr) < 13 {
return errPalamInvalidStackItem
}
requestID, err := arr[0].TryInteger()
if err != nil {
return err
}
d.RequestID = requestID.Uint64()
flowIDBytes, err := arr[1].TryBytes()
if err != nil {
return err
}
d.FlowID, err = util.Uint256DecodeBytesBE(flowIDBytes)
if err != nil {
return err
}
caseIDBytes, err := arr[2].TryBytes()
if err != nil {
return err
}
d.CaseID = string(caseIDBytes)
reasonBytes, err := arr[3].TryBytes()
if err != nil {
return err
}
d.Reason = string(reasonBytes)
requesterBytes, err := arr[4].TryBytes()
if err != nil {
return err
}
d.Requester, err = util.Uint160DecodeBytesBE(requesterBytes)
if err != nil {
return err
}
role, err := arr[5].TryInteger()
if err != nil {
return err
}
d.RequesterRole = PalamRole(role.Uint64())
required, err := arr[6].TryInteger()
if err != nil {
return err
}
d.RequiredApprovals = uint32(required.Uint64())
approvalsArr, ok := arr[7].Value().([]stackitem.Item)
if !ok {
return errPalamInvalidStackItem
}
d.Approvals = make([]util.Uint160, len(approvalsArr))
for i, a := range approvalsArr {
aBytes, err := a.TryBytes()
if err != nil {
return err
}
d.Approvals[i], err = util.Uint160DecodeBytesBE(aBytes)
if err != nil {
return err
}
}
timesArr, ok := arr[8].Value().([]stackitem.Item)
if !ok {
return errPalamInvalidStackItem
}
d.ApprovalTimes = make([]uint32, len(timesArr))
for i, t := range timesArr {
tInt, err := t.TryInteger()
if err != nil {
return err
}
d.ApprovalTimes[i] = uint32(tInt.Uint64())
}
status, err := arr[9].TryInteger()
if err != nil {
return err
}
d.Status = DeclassifyStatus(status.Uint64())
createdAt, err := arr[10].TryInteger()
if err != nil {
return err
}
d.CreatedAt = uint32(createdAt.Uint64())
expiresAt, err := arr[11].TryInteger()
if err != nil {
return err
}
d.ExpiresAt = uint32(expiresAt.Uint64())
grantedAt, err := arr[12].TryInteger()
if err != nil {
return err
}
d.GrantedAt = uint32(grantedAt.Uint64())
return nil
}
// AccessLog represents a record of data access.
type AccessLog struct {
LogID uint64 // Unique identifier
FlowID util.Uint256 // Which flow was accessed
Accessor util.Uint160 // Who accessed
AccessType AccessType // Type of access
Timestamp uint32 // Block height
Details string // Additional context
}
// ToStackItem converts AccessLog to a stack item.
func (a *AccessLog) ToStackItem() stackitem.Item {
return stackitem.NewArray([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(a.LogID))),
stackitem.NewByteArray(a.FlowID.BytesBE()),
stackitem.NewByteArray(a.Accessor.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(a.AccessType))),
stackitem.NewBigInteger(big.NewInt(int64(a.Timestamp))),
stackitem.NewByteArray([]byte(a.Details)),
})
}
// FromStackItem populates AccessLog from a stack item.
func (a *AccessLog) FromStackItem(item stackitem.Item) error {
arr, ok := item.Value().([]stackitem.Item)
if !ok || len(arr) < 6 {
return errPalamInvalidStackItem
}
logID, err := arr[0].TryInteger()
if err != nil {
return err
}
a.LogID = logID.Uint64()
flowIDBytes, err := arr[1].TryBytes()
if err != nil {
return err
}
a.FlowID, err = util.Uint256DecodeBytesBE(flowIDBytes)
if err != nil {
return err
}
accessorBytes, err := arr[2].TryBytes()
if err != nil {
return err
}
a.Accessor, err = util.Uint160DecodeBytesBE(accessorBytes)
if err != nil {
return err
}
accessType, err := arr[3].TryInteger()
if err != nil {
return err
}
a.AccessType = AccessType(accessType.Uint64())
timestamp, err := arr[4].TryInteger()
if err != nil {
return err
}
a.Timestamp = uint32(timestamp.Uint64())
detailsBytes, err := arr[5].TryBytes()
if err != nil {
return err
}
a.Details = string(detailsBytes)
return nil
}
// FlowAttachment represents additional data attached to a flow.
type FlowAttachment struct {
AttachmentID uint64 // Unique identifier
FlowID util.Uint256 // Parent flow
AttachmentType string // Type of attachment
EncryptedData []byte // Encrypted content
Attacher util.Uint160 // Who attached
AttachedAt uint32 // Block height
}
// ToStackItem converts FlowAttachment to a stack item.
func (fa *FlowAttachment) ToStackItem() stackitem.Item {
return stackitem.NewArray([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(fa.AttachmentID))),
stackitem.NewByteArray(fa.FlowID.BytesBE()),
stackitem.NewByteArray([]byte(fa.AttachmentType)),
stackitem.NewByteArray(fa.EncryptedData),
stackitem.NewByteArray(fa.Attacher.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(fa.AttachedAt))),
})
}
// FromStackItem populates FlowAttachment from a stack item.
func (fa *FlowAttachment) FromStackItem(item stackitem.Item) error {
arr, ok := item.Value().([]stackitem.Item)
if !ok || len(arr) < 6 {
return errPalamInvalidStackItem
}
attachmentID, err := arr[0].TryInteger()
if err != nil {
return err
}
fa.AttachmentID = attachmentID.Uint64()
flowIDBytes, err := arr[1].TryBytes()
if err != nil {
return err
}
fa.FlowID, err = util.Uint256DecodeBytesBE(flowIDBytes)
if err != nil {
return err
}
typeBytes, err := arr[2].TryBytes()
if err != nil {
return err
}
fa.AttachmentType = string(typeBytes)
fa.EncryptedData, err = arr[3].TryBytes()
if err != nil {
return err
}
attacherBytes, err := arr[4].TryBytes()
if err != nil {
return err
}
fa.Attacher, err = util.Uint160DecodeBytesBE(attacherBytes)
if err != nil {
return err
}
attachedAt, err := arr[5].TryInteger()
if err != nil {
return err
}
fa.AttachedAt = uint32(attachedAt.Uint64())
return nil
}
// RolePermissions defines what each role can do.
type RolePermissions struct {
CanViewAggregate bool // See totals without identities
CanViewIdentities bool // See participant identities
CanViewDocuments bool // See attached documents
CanAttachData bool // Add metadata to flows
CanRequestDeclassify bool // Initiate declassification
CanApproveDeclassify bool // Vote on declassification requests
}
// ToStackItem converts RolePermissions to a stack item.
func (rp *RolePermissions) ToStackItem() stackitem.Item {
return stackitem.NewArray([]stackitem.Item{
stackitem.NewBool(rp.CanViewAggregate),
stackitem.NewBool(rp.CanViewIdentities),
stackitem.NewBool(rp.CanViewDocuments),
stackitem.NewBool(rp.CanAttachData),
stackitem.NewBool(rp.CanRequestDeclassify),
stackitem.NewBool(rp.CanApproveDeclassify),
})
}
// FromStackItem populates RolePermissions from a stack item.
func (rp *RolePermissions) FromStackItem(item stackitem.Item) error {
arr, ok := item.Value().([]stackitem.Item)
if !ok || len(arr) < 6 {
return errPalamInvalidStackItem
}
viewAgg, err := arr[0].TryBool()
if err != nil {
return err
}
rp.CanViewAggregate = viewAgg
viewId, err := arr[1].TryBool()
if err != nil {
return err
}
rp.CanViewIdentities = viewId
viewDoc, err := arr[2].TryBool()
if err != nil {
return err
}
rp.CanViewDocuments = viewDoc
attach, err := arr[3].TryBool()
if err != nil {
return err
}
rp.CanAttachData = attach
reqDecl, err := arr[4].TryBool()
if err != nil {
return err
}
rp.CanRequestDeclassify = reqDecl
appDecl, err := arr[5].TryBool()
if err != nil {
return err
}
rp.CanApproveDeclassify = appDecl
return nil
}
// PalamConfig represents configurable parameters for TransparencyLedger.
type PalamConfig struct {
MinApprovals uint32 // Minimum approvals for declassification (default: 2)
MaxApprovals uint32 // Maximum approvers allowed (default: 5)
DefaultExpiration uint32 // Default expiration in blocks (default: 7 days worth)
LogAllAccess bool // Whether to log all access (default: true)
LogRetentionDays uint32 // How long to keep logs (default: 365)
MaxFlowsPerBlock uint32 // Rate limit for flows (default: 1000)
MaxRequestsPerDay uint32 // Rate limit for declassify requests (default: 10)
}
// ToStackItem converts PalamConfig to a stack item.
func (lc *PalamConfig) ToStackItem() stackitem.Item {
return stackitem.NewArray([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(lc.MinApprovals))),
stackitem.NewBigInteger(big.NewInt(int64(lc.MaxApprovals))),
stackitem.NewBigInteger(big.NewInt(int64(lc.DefaultExpiration))),
stackitem.NewBool(lc.LogAllAccess),
stackitem.NewBigInteger(big.NewInt(int64(lc.LogRetentionDays))),
stackitem.NewBigInteger(big.NewInt(int64(lc.MaxFlowsPerBlock))),
stackitem.NewBigInteger(big.NewInt(int64(lc.MaxRequestsPerDay))),
})
}
// FromStackItem populates PalamConfig from a stack item.
func (lc *PalamConfig) FromStackItem(item stackitem.Item) error {
arr, ok := item.Value().([]stackitem.Item)
if !ok || len(arr) < 7 {
return errPalamInvalidStackItem
}
minApprovals, err := arr[0].TryInteger()
if err != nil {
return err
}
lc.MinApprovals = uint32(minApprovals.Uint64())
maxApprovals, err := arr[1].TryInteger()
if err != nil {
return err
}
lc.MaxApprovals = uint32(maxApprovals.Uint64())
defaultExp, err := arr[2].TryInteger()
if err != nil {
return err
}
lc.DefaultExpiration = uint32(defaultExp.Uint64())
logAll, err := arr[3].TryBool()
if err != nil {
return err
}
lc.LogAllAccess = logAll
retention, err := arr[4].TryInteger()
if err != nil {
return err
}
lc.LogRetentionDays = uint32(retention.Uint64())
maxFlows, err := arr[5].TryInteger()
if err != nil {
return err
}
lc.MaxFlowsPerBlock = uint32(maxFlows.Uint64())
maxReqs, err := arr[6].TryInteger()
if err != nil {
return err
}
lc.MaxRequestsPerDay = uint32(maxReqs.Uint64())
return nil
}
// DefaultPalamConfig returns the default configuration.
func DefaultPalamConfig() *PalamConfig {
return &PalamConfig{
MinApprovals: 2,
MaxApprovals: 5,
DefaultExpiration: 604800, // ~7 days in blocks (1 block/sec)
LogAllAccess: true,
LogRetentionDays: 365,
MaxFlowsPerBlock: 1000,
MaxRequestsPerDay: 10,
}
}
// DefaultRolePermissions returns permissions for each role.
func DefaultRolePermissions(role PalamRole) *RolePermissions {
switch role {
case PalamRoleConsumer:
return &RolePermissions{
CanViewAggregate: true,
CanViewIdentities: false,
CanViewDocuments: false,
CanAttachData: false,
CanRequestDeclassify: false,
CanApproveDeclassify: false,
}
case PalamRoleMerchant, PalamRoleDistributor, PalamRoleProducer, PalamRoleNGO:
return &RolePermissions{
CanViewAggregate: true,
CanViewIdentities: true,
CanViewDocuments: true,
CanAttachData: true,
CanRequestDeclassify: false,
CanApproveDeclassify: false,
}
case PalamRoleAuditor:
return &RolePermissions{
CanViewAggregate: true,
CanViewIdentities: false,
CanViewDocuments: false,
CanAttachData: false,
CanRequestDeclassify: true,
CanApproveDeclassify: false,
}
default:
return &RolePermissions{}
}
}