> For the complete documentation index, see [llms.txt](https://stellar.gitbook.io/module-library/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stellar.gitbook.io/module-library/identity-management/tier-based-role-certifier/specification.md).

# Specification

*Authors: BlockScience and SDF, September 2023*

> ### Introduction

A notebook containing an end-to-end example implementation for this document can be found on the [gov-modules-demos GitHub repository](https://github.com/BlockScience/gov-modules-demos/blob/main/demos/tier_based_role_certifier.ipynb).

### Definitions

* Attestation: Retrievable boolean assertion. Can contain or be assigned an expiry timestamp. Can be sourced exogenously (eg. by retrieving stamps through oracles) or endogenously (eg. by attestating instantaneously through procedural rules).
* Role: Computable boolean assertion on which the result depends on the aggregation of pre-defined prior attestations.
* Qualifier: Attestation source that can be used for attesting for a given role.
* Disqualifier: Qualifier that will automatically deny a given role attestation.
* Autoqualifier: Qualifier that will automatically approve a given role attestation, provided that it wasn't disqualified beforehand.
* Conditional Qualifier: Qualifier on which the result will add to the accumulated approval criteria for a given role attestation.
* Attestation Weight: Transforms a boolean assertion into a real number. Used for controlling the relative importance for each conditional qualifier.
* Qualifier Aggregator: Transforms a list of real numbers into a single real number. Used for transforming the conditional qualifier weights into a single number that can be compared against.
* Conditional Threshold: Comparison number that is used for transforming a single real number into a boolean assertion. Used for determining whatever the aggregated conditional qualifiers do approve a positive result for the role attestation or not.

### Example Implementation in Python

#### Definitions

```python
AttestationUUID = str
AttestationWeight = float
Days = int


class AttestationProbabilityArgs(NamedTuple):
    attest_probability: float
    invoke_probability: float
    issuance_mean_expiry_in_days: Days
    issuance_std_expiry_in_days: Days


@dataclass
class Attestation():
    attestation_uuid: AttestationUUID
    result: bool  # Between 0.0 and 1.0
    issuance: Days
    expiry: Days


@dataclass
class Agent():
    attestations: dict[AttestationUUID, Attestation]

    def valid_attestations(self, reference_time) -> list[Attestation]:
        return [a
                for a in self.attestations.values()
                if a.expiry > reference_time
                and a.issuance <= reference_time]

    def sucessful_attestations(self, reference_time) -> list[Attestation]:
        return [a
                for a in self.valid_attestations(reference_time)
                if a.result == True]



@dataclass
class RoleCertifier():
    attestation_uuid: AttestationUUID
    issuance_validity: Days

    conditional_qualifiers: dict[AttestationUUID, AttestationWeight]
    auto_qualifers: set[AttestationUUID]
    disqualifiers: set[AttestationUUID]

    qualifier_aggregator: Callable[[dict], float]
    conditional_threshold: float

    def generate_attestation(self, result: bool, time: Days) -> Attestation:
        return Attestation(self.attestation_uuid,
                           result,
                           time,
                           time + self.issuance_validity)

    def agent_certification_result(self,
                                   agent: PassportDemoAgent,
                                   time: Days) -> bool:
        agent_sucessful_attestations = set(a.attestation_uuid
                                           for a in agent.valid_attestations(time)
                                           if a.result == True)

        if len(agent_sucessful_attestations & self.disqualifiers) > 0:
            return False
        elif len(agent_sucessful_attestations & self.auto_qualifers) > 0:
            return True
        else:
            conditional_attestations = set(self.conditional_qualifiers.keys())
            agent_relevant_attestations = agent_sucessful_attestations & conditional_attestations

            agent_conditional_values = {a: self.conditional_qualifiers[a]
                                        for a
                                        in agent_relevant_attestations}
            agent_conditional_value = self.qualifier_aggregator(
                agent_conditional_values)
            if agent_conditional_value >= self.conditional_threshold:
                return True
            else:
                return False

    def attestate_agent(self, agent: PassportDemoAgent, time: Days):
        return self.generate_attestation(self.agent_certification_result(agent, time), time)
```

#### Example instantiation of TRC

```python
def compound_product(lst): 
    if len(lst) > 1:
        return reduce(lambda x, y: (1 + x) * (1 + y) - 1, list(lst))
    elif len(lst) == 1:
        return lst[0]
    else:
        return 0.0


role_A = RoleCertifier(attestation_uuid='role_A_attestation',
                          issuance_validity=90,
                          conditional_qualifiers={
                              'att_1': 1, 'att_2': 2, 'att_3': 3},
                          auto_qualifers=set(),
                          disqualifiers={'att_ban'},
                          qualifier_aggregator=lambda atts: sum(atts.values()),
                          conditional_threshold=2)

role_B = RoleCertifier(attestation_uuid='role_B_attestation',
                          issuance_validity=30,
                          conditional_qualifiers={
                              'att_3': 0.3, 'att_4': 0.25, 'att_5': 0.2},
                          auto_qualifers={'role_A_attestation'},
                          disqualifiers={'att_ban'},
                          qualifier_aggregator=lambda atts: compound_product(
                              tuple(atts.values())),
                          conditional_threshold=0.25)

EXAMPLE_ATTESTATION_PROVIDERS = {
    'att_1': AttestationProbabilityArgs(0.2, 0.1, 7, 10),
    'att_2': AttestationProbabilityArgs(0.2, 0.1, 14, 10),
    'att_3': AttestationProbabilityArgs(0.05, 0.1, 30, 10),
    'att_4': AttestationProbabilityArgs(0.4, 0.05, 15, 3),
    'att_5': AttestationProbabilityArgs(0.6, 0.5, 40, 10),
    'att_ban': AttestationProbabilityArgs(0.02, 0.05, 120, 5)
}

EXAMPLE_ROLE_CERTIFIERS = [role_A, role_B]
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://stellar.gitbook.io/module-library/identity-management/tier-based-role-certifier/specification.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
