GASP

Governance

The GASP twin gives every agent the same view of what metrics exist and how they connect. That is a feature, not a bug. But agents act on behalf of users, and users have different access needs. This page is GASP's opinion on how to scope permissions in an agentic SaaS system without building a new policy engine.

The Problem

If every agent reads the same twin, and every user can invoke any agent, then by default every user has access to every metric. A Support Manager's retention agent could ask the Finance twin for CAC. A sales rep's pipeline agent could read competitor win rates in other territories. Without governance the twin becomes a bypass around carefully-designed enterprise access controls.

The mistake is treating this as a new problem. It is not. Enterprise access control is a well-studied domain with proven patterns. GASP's job is to give those patterns a shared vocabulary, not to reinvent them.

The Three-Layer Model

Access control in an agentic system operates at three distinct layers. Conflating them is where most implementations fail.

1

Model Layer

Always visible

Every user can see what metrics exist, their canonical definitions, their relationships and their required fields. The model is documentation. Withholding it creates shadow systems and duplicate definitions. A Support Manager should know what CAC is and where it lives in the graph, even if they cannot see the current number.

2

Computation Layer

Permission-gated

Can a user compute the current value of a metric? This is the real enforcement boundary. It lives in the warehouse via row-level security, column masking or a query rewriter. The agent does not make this decision. The warehouse does. When a query runs, it runs with the user's identity and the user's permissions.

3

Agent Layer

Delegated identity

Agents always act on behalf of a user and inherit that user's scope. A retention agent invoked by a Finance Manager sees different numbers than the same agent invoked by a Support Manager. Elevated service identities (board prep, compliance audit) are explicit, audited exceptions.

What GASP Adds

Two metric-level classifications give downstream policy systems stable identifiers to reference. These are recommendations, not enforcement. Your organization may reasonably choose different defaults.

Sensitivity Tier

Aligns with ISO 27001, OSSA data_classification and AWS Cedar common patterns. See the glossary entry for the canonical definition.

Tier Description
public Shareable externally with no restriction (rare for internal SaaS metrics)
internal Shareable across the organization. Default for most operational metrics
confidential Cross-functional but sensitive. Typically restricted to managers and above
restricted Highly sensitive. Executive and finance-leadership only by default

Access Scope

Describes whether a metric is naturally filterable per user context (the ReBAC/ABAC dimension). See the glossary entry for the canonical definition.

Scope Description
unscoped Same value for everyone with access (e.g. company-wide ARR)
department-scoped Filtered by the viewer's department context
owner-scoped Visible only for records the viewer owns or manages (individual, team, territory, book or segment — interpretation lives in the adapter)

Recommended Classifications

Default sensitivity and scope for every metric in the GASP relationship graph. Use these as a starting point. Your organization's risk profile may justify different choices.

Metric Sensitivity Scope
rule_of_40 restricted unscoped
operating_margin restricted unscoped
fcf restricted unscoped
burn_rate restricted unscoped
revenue_per_employee restricted unscoped
magic_number restricted unscoped
employee_turnover restricted unscoped
enps restricted unscoped
pipeline_value confidential owner-scoped
pipeline_coverage confidential owner-scoped
acv confidential owner-scoped
quota_attainment confidential owner-scoped
win_rate confidential department-scoped
forecast_accuracy confidential department-scoped
cpl confidential department-scoped
marketing_sourced_pipeline confidential department-scoped
expansion_rate confidential department-scoped
renewal_rate confidential department-scoped
partner_sourced_revenue confidential department-scoped
arr confidential unscoped
mrr confidential unscoped
arpa confidential unscoped
mrr_growth_rate confidential unscoped
new_mrr confidential unscoped
expansion_mrr confidential unscoped
churned_mrr confidential unscoped
contraction_mrr confidential unscoped
net_new_mrr confidential unscoped
nrr confidential unscoped
grr confidential unscoped
gross_margin confidential unscoped
logo_churn_rate confidential unscoped
revenue_churn_rate confidential unscoped
cac confidential unscoped
ltv confidential unscoped
ltv_cac_ratio confidential unscoped
cac_payback confidential unscoped
marketing_cac confidential unscoped
dso confidential unscoped
health_score internal owner-scoped
at_risk_rate internal owner-scoped
sales_cycle internal department-scoped
qbr_completion internal department-scoped
csat internal department-scoped
frt internal department-scoped
ticket_volume internal department-scoped
ttfv internal department-scoped
onboarding_completion internal department-scoped
pqas internal department-scoped
deployment_frequency internal department-scoped
mttr internal department-scoped
nps internal unscoped
mqls internal unscoped
sqls internal unscoped
lvr internal unscoped
self_service_rate internal unscoped
activation_rate internal unscoped
dau_mau internal unscoped
feature_adoption internal unscoped
uptime internal unscoped

A Decision Framework

When classifying a new metric, work through three questions in order:

  1. Who needs it by default? If the answer is "the whole company," the tier is internal. If the answer is "managers and above," it is confidential. If it is "finance leadership and the CEO," it is restricted.
  2. Is it filterable? If the same metric makes sense with per-user context (my pipeline, my accounts, my team's tickets), give it a scope other than unscoped. A sales rep should see pipeline but only their own.
  3. Does computing it leak something the value alone does not? Aggregate marketing spend is less sensitive than per-campaign spend. Aggregate CAC is less sensitive than CAC broken down by channel. Choose the aggregation that provides insight without exposing competitive detail.

Integration Patterns

GASP tags are metadata. Enforcement happens in existing policy systems. Three patterns cover most implementations.

Cedar Policies

Cedar is an open-source policy language used by AWS Verified Permissions and referenced in the OSSA governance schema. Express GASP classifications as resource attributes:

// Principal: User with department and clearance attributes
// Resource: GASP metric with sensitivityTier and accessScope

permit (
  principal in Department::"Finance",
  action == Action::"query",
  resource
)
when {
  resource has sensitivityTier &&
  resource.sensitivityTier in ["public", "internal", "confidential", "restricted"]
};

// Department managers see internal + confidential for their dept
permit (
  principal,
  action == Action::"query",
  resource
)
when {
  principal has role && principal.role == "manager" &&
  resource.sensitivityTier in ["internal", "confidential"] &&
  (resource.accessScope == "unscoped" ||
   resource.department == principal.department)
};

// Everyone sees internal + unscoped
permit (
  principal,
  action == Action::"query",
  resource
)
when {
  resource.sensitivityTier == "internal" &&
  resource.accessScope == "unscoped"
};

// Restricted tier: explicit allowlist only
forbid (
  principal,
  action == Action::"query",
  resource
)
unless {
  resource.sensitivityTier != "restricted" ||
  principal in Group::"FinanceLeadership"
};

Open Policy Agent (Rego)

OPA is the enterprise default for policy-as-code. The same GASP classifications expressed in Rego:

package gasp.authz

import rego.v1

default allow := false

# Everyone sees internal + unscoped metrics
allow if {
  input.resource.sensitivityTier == "internal"
  input.resource.accessScope == "unscoped"
}

# Department managers see confidential within their department
allow if {
  input.principal.role == "manager"
  input.resource.sensitivityTier in {"internal", "confidential"}
  manager_can_see_scope
}

manager_can_see_scope if input.resource.accessScope == "unscoped"
manager_can_see_scope if {
  input.resource.accessScope == "department-scoped"
  input.resource.department == input.principal.department
}
manager_can_see_scope if {
  input.resource.accessScope == "owner-scoped"
  input.resource.owner == input.principal.user_id
}

# Restricted requires explicit finance leadership membership
allow if {
  input.resource.sensitivityTier == "restricted"
  "finance_leadership" in input.principal.groups
}

Warehouse Row-Level Security

The enforcement actually applies to data, not metadata. Snowflake, BigQuery and Postgres all support row-level security where the user's identity filters the result set. Use GASP classifications to generate these policies programmatically.

-- Snowflake: owner-scoped pipeline visibility
-- "Owner" can be an individual rep, a territory, a book or a segment.
-- Interpretation lives in the ownership_assignments table, not in GASP.
CREATE ROW ACCESS POLICY pipeline_owner_policy AS (owner_id VARCHAR)
  RETURNS BOOLEAN ->
    CASE
      WHEN CURRENT_ROLE() IN ('SYSADMIN', 'FINANCE_LEADERSHIP') THEN TRUE
      WHEN CURRENT_USER() IN (
        SELECT user_id FROM governance.ownership_assignments
        WHERE assigned_owner_id = owner_id
      ) THEN TRUE
      ELSE FALSE
    END;

ALTER TABLE fct_opportunities
  ADD ROW ACCESS POLICY pipeline_owner_policy ON (owner_id);

-- BigQuery: restricted-tier column masking via data policy
CREATE OR REPLACE TABLE company_metrics OPTIONS (
  policy_tags_on_columns = [
    ('burn_rate',  'projects/acme/locations/us/taxonomies/gasp/policyTags/restricted'),
    ('operating_margin', 'projects/acme/locations/us/taxonomies/gasp/policyTags/restricted')
  ]
);

MCP OAuth Scopes

When an agent calls the GASP MCP server it passes a user token. Map GASP sensitivity tiers to OAuth scopes to gate which MCP tools the agent can invoke on the user's behalf.

// OAuth scope mapping for GASP MCP tools
{
  "scopes": {
    "gasp:read:public":       ["lookup_metric", "search", "get_relationships"],
    "gasp:read:internal":     ["list_metrics", "get_data_requirements"],
    "gasp:read:confidential": ["generate_query"],
    "gasp:read:restricted":   ["validate_adapter"]
  },
  "role_scopes": {
    "ic":       ["gasp:read:public", "gasp:read:internal"],
    "manager":  ["gasp:read:public", "gasp:read:internal", "gasp:read:confidential"],
    "exec":     ["gasp:read:public", "gasp:read:internal",
                 "gasp:read:confidential", "gasp:read:restricted"]
  }
}

Agent Integration Patterns

The protocols covered above handle single-user data access. Agentic systems add a second identity layer: agents act on behalf of users but have their own permissions too. This is where OSSA (agent contracts) and A2A (inter-agent communication) intersect with GASP.

The Two-Ceiling Model

The single most common mistake in agentic systems is letting agents run with service accounts that have more access than the user who invoked them. Effective access is the intersection of three ceilings:

effective_access = min(agent_clearance, user_clearance, metric_sensitivity)
  • Agent clearance comes from the OSSA manifest (authorization.clearance_level)
  • User clearance comes from your identity provider (Okta, Google Workspace, Azure AD)
  • Metric sensitivity comes from GASP (accessControl.classifications)

The warehouse enforces the intersection via row-level security and column masking. Neither the agent nor the application makes this decision. They describe constraints. The enforcement layer computes the answer.

Token Propagation (A2A)

When a coordinator agent calls a specialist via A2A, the user's token must propagate through the call chain. If the coordinator uses its own service token, privilege escalates silently. The pattern is OAuth 2 Token Exchange (RFC 8693):

// Coordinator receives a request with the user's token
// It does NOT use its own service token to call specialists

// 1. Coordinator exchanges the user token for a delegated token
//    scoped to the specialist audience
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&audience=https://agents.acme.com/retention-specialist
&actor_token=
&actor_token_type=urn:ietf:params:oauth:token-type:access_token
&scope=gasp:read:confidential

// 2. Coordinator calls the specialist with the delegated token
POST https://agents.acme.com/retention-specialist/message:send
Authorization: Bearer 
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "req-coord-001",
  "method": "SendMessage",
  "params": { "message": { "role": "user", "parts": [...] } }
}

// The specialist now executes warehouse queries with the ORIGINAL user's
// identity. If the user cannot see restricted metrics, neither can the
// specialist acting on their behalf. No privilege escalation via chaining.

Human Review for Restricted Access (OSSA)

OSSA's cognition.governance.human_review_triggers lets you require human approval before an agent accesses sensitive resources. This is a cheap safety valve for GASP's restricted tier:

# In the agent's .ossa.yaml manifest
apiVersion: ossa/v0.5.0
kind: Agent
metadata:
  name: gasp-retention-analyst

cognition:
  governance:
    human_review_triggers:
      - trigger: tool_access
        condition: resource.gasp_sensitivity == "restricted"
        reviewer: finance_leadership
        sla_hours: 4
      - trigger: data_export
        condition: result.record_count > 1000
        reviewer: data_governance
    audit_required: true

governance:
  authorization:
    clearance_level: 3  # can HANDLE up to confidential without review
    tool_permissions:
      - tool: generate_query
        access: read
        constraints:
          - "resource.gasp_sensitivity != 'restricted' OR approved_via_review"

When the retention agent traces NRR down to Burn Rate (a restricted metric), the OSSA runtime pauses the agent and requests approval from Finance Leadership. The user sees "waiting for review" rather than getting the number silently. This converts the GASP classification into an enforced workflow without writing custom policy code.

The Audit Tuple Requirement

Traditional warehouse audit logs capture one identity: whoever ran the query. In agentic systems you need three: the user who asked, the agent that ran and the session that connected them. Without all three your audit trail is broken the first time an agent does something unexpected.

-- Extend warehouse queries to carry the full identity tuple
-- Snowflake query tag example
ALTER SESSION SET QUERY_TAG = OBJECT_CONSTRUCT(
  'user_id',     'user-sarah-cfo',
  'agent_id',    'gasp-retention-analyst@1.0.0',
  'session_id',  'a2a-ctx-abc-123',
  'parent_task', 'task-coord-001',
  'gasp_metric', 'nrr',
  'tier',        'confidential'
)::STRING;

-- Then correlate across four log sources:
--   1. Identity provider (user authentication)
--   2. A2A message log (agent invocations)
--   3. MCP server log (tool calls)
--   4. Warehouse query log (actual data access)
-- Joined on session_id, you get the complete chain from
-- "user Sarah asked a question" to "specifically these rows were read".

Neither OSSA nor A2A standardize this audit format yet. GASP's opinion: always propagate the tuple, always join across the four logs, always retain for the period your compliance framework requires (typically 90-365 days).

Who Does What

Concern Owner Where it is configured
Metric sensitivity classification GASP accessControl.classifications in ontology
Agent clearance ceiling OSSA authorization.clearance_level in agent manifest
User identity and role Identity provider Okta, Google Workspace, Azure AD
Token propagation between agents A2A OAuth 2 Token Exchange (RFC 8693)
Human-in-the-loop gates OSSA cognition.governance.human_review_triggers
Policy evaluation Cedar / OPA Policy-as-code referencing GASP tier tags
Row-level and column enforcement Warehouse Snowflake RLS, BigQuery policy tags, Postgres RLS
Audit logging Identity + A2A + MCP + Warehouse Propagate (user, agent, session, task) tuple through all four

Common Dilemmas

The Support Manager and CAC

A Support Manager wants to understand CAC to argue that reducing support friction lowers churn and improves unit economics. GASP tags CAC as confidential and unscoped. Should they see it?

Recommended resolution: Yes, in aggregate. A Support Manager should see company-level CAC as part of operating context. They should not see CAC broken down by channel, by quarter or by campaign. Those finer-grained views are where competitive and strategic sensitivity lives. The classification is a starting point, not a veto.

Board Prep Agent and Restricted Metrics

The board deck needs burn rate, runway and operating margin. All are restricted. Should an automated agent be able to pull these?

Recommended resolution: Yes, via an explicit service identity with elevated scope, not via delegation from the user who invoked it. The agent runs as a governance-approved service account with its own audit trail. The CFO invokes the agent, but the agent's permissions come from its own identity, not the CFO's. Every invocation is logged. This is the same pattern as a CI pipeline with elevated deployment permissions.

Cross-Functional Dashboards

A company-wide health dashboard shows NRR, Gross Margin and Employee NPS. Three different tiers, three different intended audiences. How should this be governed?

Recommended resolution: The dashboard renders what each viewer is allowed to see. A department manager sees NRR and Gross Margin but the eNPS panel is masked or hidden. The dashboard is static code; the filtering happens at the warehouse layer per the row-level policies above. No special dashboard-level permission logic.

What about agents that call other agents?

A coordinator agent invokes a Finance specialist agent to compute Rule of 40. The coordinator was invoked by a Sales Manager. Whose permissions apply?

Recommended resolution: Always the originating human identity. Protocols like A2A propagate the caller token. The Finance specialist executes the query with the Sales Manager's credentials, which hit the warehouse's row-level policies. If the Sales Manager cannot see restricted metrics, neither can any agent acting on their behalf. Agents do not accumulate privilege through chaining.

What GASP Does Not Do

GASP is a standard, not a runtime. Specifically:

  • GASP does not enforce permissions. Enforcement belongs in Cedar, OPA, your identity provider or your warehouse.
  • GASP does not define user roles. Your organization designs its own role hierarchy. GASP just gives your roles a vocabulary to reference.
  • GASP does not audit access. Audit logging happens where queries run (the warehouse) and where tokens are issued (the identity layer).
  • GASP does not replace your data governance program. It complements SOC2, ISO 27001 and existing compliance frameworks.

The value is in the shared vocabulary. When every metric has a stable ID, a recommended tier and a recommended scope, policies across tools become portable. A Cedar policy written against GASP metric IDs works whether your warehouse is Snowflake or BigQuery, and whether your identity provider is Okta or Google Workspace.

Try searching for:

navigateselect