// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.29.0 // source: grants.sql package entitlements import ( "context" "database/sql" "time" "github.com/google/uuid" "github.com/lib/pq" "github.com/sqlc-dev/pqtype" ) const countDeliveringDefaultGrants = `-- name: CountDeliveringDefaultGrants :one SELECT COUNT(DISTINCT g.grant_id) FROM core.grants g JOIN core.pool_provisions pp ON pp.grant_id = g.grant_id WHERE pp.status = 'active' AND g.grant_reason = 'default' ` // The delivering-grants caption: how many signup defaults are delivering, // excluded from the headline above. Same provision join as // CountDeliveringOperatorGrants so the two can never disagree about what // "delivering" means. func (q *Queries) CountDeliveringDefaultGrants(ctx context.Context) (int64, error) { row := q.db.QueryRowContext(ctx, countDeliveringDefaultGrants) var count int64 err := row.Scan(&count) return count, err } const countDeliveringOperatorGrants = `-- name: CountDeliveringOperatorGrants :one SELECT COUNT(DISTINCT g.grant_id) FROM core.grants g JOIN core.pool_provisions pp ON pp.grant_id = g.grant_id WHERE pp.status = 'active' AND g.grant_reason <> 'default' ` // Operator overview headline: grants someone deliberately issued that are // delivering right now. Signup defaults are excluded — conferral mints one // per org, so they drown the number an operator can act on; their count // rides the tile's caption (CountDeliveringDefaultGrants). Non-default is // exactly the operator-authored set per chk_grants_default_iff_system_authored. // // grants.status is an issuance LEDGER — it records what was written and // whether it was later revoked, not whether service is flowing today. The // current-delivery fact lives on core.pool_provisions.status, so this counts // distinct grants that own at least one active provision rather than // filtering grants.status alone. func (q *Queries) CountDeliveringOperatorGrants(ctx context.Context) (int64, error) { row := q.db.QueryRowContext(ctx, countDeliveringOperatorGrants) var count int64 err := row.Scan(&count) return count, err } const createGrant = `-- name: CreateGrant :one INSERT INTO core.grants (product_id, granted_to_org_id, granted_by_person_id, grant_reason, description, quantity, valid_from, valid_until, extends_grant_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING grant_id, product_id, granted_to_billing_account_id, granted_to_org_id, granted_to_person_id, granted_by_person_id, grant_reason, description, quantity, valid_from, valid_until, status, revoked_at, revoked_by_person_id, revocation_reason, metadata, created_at, updated_at, extends_grant_id ` type CreateGrantParams struct { ProductID string `json:"product_id"` GrantedToOrgID uuid.NullUUID `json:"granted_to_org_id"` GrantedByPersonID uuid.NullUUID `json:"granted_by_person_id"` GrantReason string `json:"grant_reason"` Description sql.NullString `json:"description"` Quantity int32 `json:"quantity"` ValidFrom time.Time `json:"valid_from"` ValidUntil sql.NullTime `json:"valid_until"` ExtendsGrantID uuid.NullUUID `json:"extends_grant_id"` } func (q *Queries) CreateGrant(ctx context.Context, arg CreateGrantParams) (Grant, error) { row := q.db.QueryRowContext(ctx, createGrant, arg.ProductID, arg.GrantedToOrgID, arg.GrantedByPersonID, arg.GrantReason, arg.Description, arg.Quantity, arg.ValidFrom, arg.ValidUntil, arg.ExtendsGrantID, ) var i Grant err := row.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ) return i, err } const expireGrant = `-- name: ExpireGrant :one UPDATE core.grants SET status = 'expired' WHERE grant_id = $1 AND status = 'active' RETURNING grant_id, product_id, granted_to_billing_account_id, granted_to_org_id, granted_to_person_id, granted_by_person_id, grant_reason, description, quantity, valid_from, valid_until, status, revoked_at, revoked_by_person_id, revocation_reason, metadata, created_at, updated_at, extends_grant_id ` // Marks a grant expired at its valid_until bound. Enacting the position end is // end_conferral's job; this is the decree half (design D5). func (q *Queries) ExpireGrant(ctx context.Context, grantID string) (Grant, error) { row := q.db.QueryRowContext(ctx, expireGrant, grantID) var i Grant err := row.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ) return i, err } const getGrantByID = `-- name: GetGrantByID :one SELECT grant_id, product_id, granted_to_billing_account_id, granted_to_org_id, granted_to_person_id, granted_by_person_id, grant_reason, description, quantity, valid_from, valid_until, status, revoked_at, revoked_by_person_id, revocation_reason, metadata, created_at, updated_at, extends_grant_id FROM core.grants WHERE grant_id = $1 ` func (q *Queries) GetGrantByID(ctx context.Context, grantID string) (Grant, error) { row := q.db.QueryRowContext(ctx, getGrantByID, grantID) var i Grant err := row.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ) return i, err } const getGrantLineage = `-- name: GetGrantLineage :many WITH RECURSIVE lineage AS ( SELECT g.grant_id, g.product_id, g.granted_to_billing_account_id, g.granted_to_org_id, g.granted_to_person_id, g.granted_by_person_id, g.grant_reason, g.description, g.quantity, g.valid_from, g.valid_until, g.status, g.revoked_at, g.revoked_by_person_id, g.revocation_reason, g.metadata, g.created_at, g.updated_at, g.extends_grant_id, 0 AS depth FROM core.grants g WHERE g.grant_id = $1 UNION ALL SELECT g.grant_id, g.product_id, g.granted_to_billing_account_id, g.granted_to_org_id, g.granted_to_person_id, g.granted_by_person_id, g.grant_reason, g.description, g.quantity, g.valid_from, g.valid_until, g.status, g.revoked_at, g.revoked_by_person_id, g.revocation_reason, g.metadata, g.created_at, g.updated_at, g.extends_grant_id, l.depth + 1 FROM core.grants g JOIN lineage l ON g.grant_id = l.extends_grant_id ) SELECT lineage.grant_id, lineage.product_id, lineage.granted_to_billing_account_id, lineage.granted_to_org_id, lineage.granted_to_person_id, lineage.granted_by_person_id, lineage.grant_reason, lineage.description, lineage.quantity, lineage.valid_from, lineage.valid_until, lineage.status, lineage.revoked_at, lineage.revoked_by_person_id, lineage.revocation_reason, lineage.metadata, lineage.created_at, lineage.updated_at, lineage.extends_grant_id FROM lineage ORDER BY lineage.depth ASC ` type GetGrantLineageRow struct { GrantID string `json:"grant_id"` ProductID string `json:"product_id"` GrantedToBillingAccountID uuid.NullUUID `json:"granted_to_billing_account_id"` GrantedToOrgID uuid.NullUUID `json:"granted_to_org_id"` GrantedToPersonID uuid.NullUUID `json:"granted_to_person_id"` GrantedByPersonID uuid.NullUUID `json:"granted_by_person_id"` GrantReason string `json:"grant_reason"` Description sql.NullString `json:"description"` Quantity int32 `json:"quantity"` ValidFrom time.Time `json:"valid_from"` ValidUntil sql.NullTime `json:"valid_until"` Status string `json:"status"` RevokedAt sql.NullTime `json:"revoked_at"` RevokedByPersonID uuid.NullUUID `json:"revoked_by_person_id"` RevocationReason sql.NullString `json:"revocation_reason"` Metadata pqtype.NullRawMessage `json:"metadata"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` ExtendsGrantID uuid.NullUUID `json:"extends_grant_id"` } // Walks the ancestry chain of the focal grant via extends_grant_id, returning // the focal grant first followed by each ancestor (parent, grandparent, ...) // in chain-walk order. Revoked or expired ancestors are included; lineage is // about who-came-before, not current validity. func (q *Queries) GetGrantLineage(ctx context.Context, grantID string) ([]GetGrantLineageRow, error) { rows, err := q.db.QueryContext(ctx, getGrantLineage, grantID) if err != nil { return nil, err } defer rows.Close() items := []GetGrantLineageRow{} for rows.Next() { var i GetGrantLineageRow if err := rows.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listAllGrants = `-- name: ListAllGrants :many SELECT grant_id, product_id, granted_to_billing_account_id, granted_to_org_id, granted_to_person_id, granted_by_person_id, grant_reason, description, quantity, valid_from, valid_until, status, revoked_at, revoked_by_person_id, revocation_reason, metadata, created_at, updated_at, extends_grant_id FROM core.grants ORDER BY created_at DESC ` func (q *Queries) ListAllGrants(ctx context.Context) ([]Grant, error) { rows, err := q.db.QueryContext(ctx, listAllGrants) if err != nil { return nil, err } defer rows.Close() items := []Grant{} for rows.Next() { var i Grant if err := rows.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listDeliveringGrantsByOrgID = `-- name: ListDeliveringGrantsByOrgID :many SELECT DISTINCT g.grant_id, g.product_id, g.granted_to_billing_account_id, g.granted_to_org_id, g.granted_to_person_id, g.granted_by_person_id, g.grant_reason, g.description, g.quantity, g.valid_from, g.valid_until, g.status, g.revoked_at, g.revoked_by_person_id, g.revocation_reason, g.metadata, g.created_at, g.updated_at, g.extends_grant_id FROM core.grants g INNER JOIN core.pool_provisions p ON p.grant_id = g.grant_id WHERE g.granted_to_org_id = $1 AND p.status = 'active' ORDER BY g.created_at DESC ` // Returns only grants currently delivering entitlements to a pool in the // given org — i.e. grants with at least one provision in status='active'. // Used by the member-facing Sources panel where audit history would be // noise (members only need to see what they actually have right now). // DISTINCT collapses multi-provision grants to one row. func (q *Queries) ListDeliveringGrantsByOrgID(ctx context.Context, grantedToOrgID uuid.NullUUID) ([]Grant, error) { rows, err := q.db.QueryContext(ctx, listDeliveringGrantsByOrgID, grantedToOrgID) if err != nil { return nil, err } defer rows.Close() items := []Grant{} for rows.Next() { var i Grant if err := rows.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGrantsByOrgID = `-- name: ListGrantsByOrgID :many SELECT grant_id, product_id, granted_to_billing_account_id, granted_to_org_id, granted_to_person_id, granted_by_person_id, grant_reason, description, quantity, valid_from, valid_until, status, revoked_at, revoked_by_person_id, revocation_reason, metadata, created_at, updated_at, extends_grant_id FROM core.grants WHERE granted_to_org_id = $1 ORDER BY created_at DESC ` func (q *Queries) ListGrantsByOrgID(ctx context.Context, grantedToOrgID uuid.NullUUID) ([]Grant, error) { rows, err := q.db.QueryContext(ctx, listGrantsByOrgID, grantedToOrgID) if err != nil { return nil, err } defer rows.Close() items := []Grant{} for rows.Next() { var i Grant if err := rows.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGrantsWithDelivery = `-- name: ListGrantsWithDelivery :many SELECT g.grant_id, g.granted_to_org_id, g.product_id, g.grant_reason, g.quantity, g.status AS grant_status, g.created_at, g.extends_grant_id, CASE WHEN BOOL_OR(p.status = 'active') THEN 'live' WHEN EXISTS ( SELECT 1 FROM core.grants child WHERE child.extends_grant_id = g.grant_id ) THEN 'superseded' ELSE 'inactive' END AS delivery_state, MAX(( SELECT child.grant_id::text FROM core.grants child WHERE child.extends_grant_id = g.grant_id ORDER BY child.created_at DESC LIMIT 1 )) AS replaced_by_grant_id, MAX(l.activated_at) AS activated_at, MAX(CASE WHEN l.status = 'ended' THEN l.ended_at END) AS ended_at FROM core.grants g LEFT JOIN core.pool_provisions p ON p.grant_id = g.grant_id LEFT JOIN core.pool_provision_ladders l ON l.provision_id = p.provision_id WHERE $1::uuid IS NULL OR g.granted_to_org_id = $1::uuid GROUP BY g.grant_id, g.granted_to_org_id, g.product_id, g.grant_reason, g.quantity, g.status, g.created_at, g.extends_grant_id ORDER BY CASE WHEN BOOL_OR(p.status = 'active') THEN 0 ELSE 1 END, g.created_at DESC ` type ListGrantsWithDeliveryRow struct { GrantID string `json:"grant_id"` GrantedToOrgID uuid.NullUUID `json:"granted_to_org_id"` ProductID string `json:"product_id"` GrantReason string `json:"grant_reason"` Quantity int32 `json:"quantity"` GrantStatus string `json:"grant_status"` CreatedAt time.Time `json:"created_at"` ExtendsGrantID uuid.NullUUID `json:"extends_grant_id"` DeliveryState string `json:"delivery_state"` ReplacedByGrantID interface{} `json:"replaced_by_grant_id"` ActivatedAt interface{} `json:"activated_at"` EndedAt interface{} `json:"ended_at"` } // The one shared delivery-state derivation (ux-honest-surfaces design // decision 1): every operator surface that lists grants renders from this // query so the grants index and the org-detail composite can never // disagree about what "live" / "superseded" / "inactive" mean. // // live -> at least one linked pool_provision is status='active' // superseded -> not live, AND a later grant actually names this one as // its extends_grant_id ancestor (a replacement was issued // -- see replaced_by_grant_id below) // inactive -> not live and not superseded: revoked/expired with no // recorded successor, or a grant that never delivered // // This is deliberately narrower than "not live" alone: a grant whose // provision simply ended (revoked, expired) with no replacement grant on // record is "inactive", not "superseded" -- "superseded" is reserved for // the case the UI can point at a specific replacing grant (the lineage // requirement: a superseded row must be able to name what replaced it). // // replaced_by_grant_id is the most recently created grant (if any) whose // extends_grant_id points at this row; NULL when nothing replaced it. // extends_grant_id (this grant's own ancestor pointer) is passed through // unchanged so the UI can walk lineage in either direction. // // Off-ladder grants (add-ons / usage / one-time) have no ladder attachment, // so activated_at / ended_at may be NULL even when delivery_state='live'. // Ordered live-first, then created_at DESC so the operationally-relevant // row appears at the top with history beneath. // // sqlc.narg(org_id): NULL returns every grant system-wide (the grants // index, /operator/grants); set, scopes to one organization (org-detail). func (q *Queries) ListGrantsWithDelivery(ctx context.Context, orgID uuid.NullUUID) ([]ListGrantsWithDeliveryRow, error) { rows, err := q.db.QueryContext(ctx, listGrantsWithDelivery, orgID) if err != nil { return nil, err } defer rows.Close() items := []ListGrantsWithDeliveryRow{} for rows.Next() { var i ListGrantsWithDeliveryRow if err := rows.Scan( &i.GrantID, &i.GrantedToOrgID, &i.ProductID, &i.GrantReason, &i.Quantity, &i.GrantStatus, &i.CreatedAt, &i.ExtendsGrantID, &i.DeliveryState, &i.ReplacedByGrantID, &i.ActivatedAt, &i.EndedAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listGrantsWithDeliveryPage = `-- name: ListGrantsWithDeliveryPage :many SELECT g.grant_id, g.granted_to_org_id, g.product_id, g.grant_reason, g.quantity, g.status AS grant_status, g.created_at, g.extends_grant_id, CASE WHEN BOOL_OR(p.status = 'active') THEN 'live' WHEN EXISTS ( SELECT 1 FROM core.grants child WHERE child.extends_grant_id = g.grant_id ) THEN 'superseded' ELSE 'inactive' END AS delivery_state, MAX(( SELECT child.grant_id::text FROM core.grants child WHERE child.extends_grant_id = g.grant_id ORDER BY child.created_at DESC LIMIT 1 )) AS replaced_by_grant_id, MAX(l.activated_at) AS activated_at, MAX(CASE WHEN l.status = 'ended' THEN l.ended_at END) AS ended_at, count(*) OVER() AS total_count FROM core.grants g LEFT JOIN core.pool_provisions p ON p.grant_id = g.grant_id LEFT JOIN core.pool_provision_ladders l ON l.provision_id = p.provision_id LEFT JOIN core.organizations org ON org.org_id = g.granted_to_org_id WHERE $1::text IS NULL OR org.name ILIKE ('%' || $1::text || '%') OR g.product_id = ANY($2::uuid[]) GROUP BY g.grant_id, g.granted_to_org_id, g.product_id, g.grant_reason, g.quantity, g.status, g.created_at, g.extends_grant_id HAVING $3::text IS NULL OR ( CASE WHEN BOOL_OR(p.status = 'active') THEN 'live' WHEN EXISTS ( SELECT 1 FROM core.grants child WHERE child.extends_grant_id = g.grant_id ) THEN 'superseded' ELSE 'inactive' END ) = $3::text ORDER BY CASE WHEN BOOL_OR(p.status = 'active') THEN 0 ELSE 1 END, g.created_at DESC LIMIT $5 OFFSET $4 ` type ListGrantsWithDeliveryPageParams struct { Q sql.NullString `json:"q"` ProductIds []string `json:"product_ids"` DeliveryState sql.NullString `json:"delivery_state"` PageOffset int32 `json:"page_offset"` PageLimit int32 `json:"page_limit"` } type ListGrantsWithDeliveryPageRow struct { GrantID string `json:"grant_id"` GrantedToOrgID uuid.NullUUID `json:"granted_to_org_id"` ProductID string `json:"product_id"` GrantReason string `json:"grant_reason"` Quantity int32 `json:"quantity"` GrantStatus string `json:"grant_status"` CreatedAt time.Time `json:"created_at"` ExtendsGrantID uuid.NullUUID `json:"extends_grant_id"` DeliveryState string `json:"delivery_state"` ReplacedByGrantID interface{} `json:"replaced_by_grant_id"` ActivatedAt interface{} `json:"activated_at"` EndedAt interface{} `json:"ended_at"` TotalCount int64 `json:"total_count"` } // Paginated, searchable, filterable system-wide variant of // ListGrantsWithDelivery for /operator/grants (operator-list-scale, // design D4). Same derivation, join shape, and ordering as // ListGrantsWithDelivery above -- do not let the two drift, and never // scope this one to an org_id; the org-detail composite keeps calling // ListGrantsWithDelivery unpaged. // // sqlc.narg(q): NULL means search is inactive and every row matches. // Non-NULL matches a grant when the granted-to organization's name // ILIKE's the term, OR the grant's product_id is present in // sqlc.narg(product_ids) -- the grants module cannot query the billing // schema directly, so the caller (Go) pre-resolves product IDs whose name // matches the search term and passes them here; a NULL or empty array // with a non-NULL q simply means the q criterion rides on org name alone. // // sqlc.narg(delivery_state): NULL returns every delivery state; otherwise // only rows whose derived state equals the value. The HAVING clause below // repeats the exact CASE expression from the SELECT list (HAVING cannot // reference a SELECT-list alias) so the filter can never disagree with // what the SELECT list -- and therefore the Go derivation reading it -- // renders as that row's state (a mixed-fixture test pins this agreement). // // count(*) OVER() is evaluated after GROUP BY/HAVING, so with the GROUP // BY below it counts grouped (one-per-grant) rows that passed WHERE and // HAVING -- the true total of matching grants, not a join-multiplied // count of the underlying pool_provisions/pool_provision_ladders rows. func (q *Queries) ListGrantsWithDeliveryPage(ctx context.Context, arg ListGrantsWithDeliveryPageParams) ([]ListGrantsWithDeliveryPageRow, error) { rows, err := q.db.QueryContext(ctx, listGrantsWithDeliveryPage, arg.Q, pq.Array(arg.ProductIds), arg.DeliveryState, arg.PageOffset, arg.PageLimit, ) if err != nil { return nil, err } defer rows.Close() items := []ListGrantsWithDeliveryPageRow{} for rows.Next() { var i ListGrantsWithDeliveryPageRow if err := rows.Scan( &i.GrantID, &i.GrantedToOrgID, &i.ProductID, &i.GrantReason, &i.Quantity, &i.GrantStatus, &i.CreatedAt, &i.ExtendsGrantID, &i.DeliveryState, &i.ReplacedByGrantID, &i.ActivatedAt, &i.EndedAt, &i.TotalCount, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listRecentGrants = `-- name: ListRecentGrants :many SELECT grant_id, product_id, granted_to_org_id, granted_by_person_id, grant_reason, quantity, created_at FROM core.grants WHERE granted_to_org_id IS NOT NULL ORDER BY created_at DESC LIMIT $1 ` type ListRecentGrantsRow struct { GrantID string `json:"grant_id"` ProductID string `json:"product_id"` GrantedToOrgID uuid.NullUUID `json:"granted_to_org_id"` GrantedByPersonID uuid.NullUUID `json:"granted_by_person_id"` GrantReason string `json:"grant_reason"` Quantity int32 `json:"quantity"` CreatedAt time.Time `json:"created_at"` } // Recent grants for the operator landing activity timeline. Returns the // raw row data with org_id + granted_by_person_id; Go-side merger resolves // those UUIDs to display names via batch lookups (avoids cross-schema // joins that don't fit per-module sqlc scope). Only org-targeted grants — // person-targeted and billing-account-targeted grants don't show up on // the org-centric operator timeline. func (q *Queries) ListRecentGrants(ctx context.Context, limit int32) ([]ListRecentGrantsRow, error) { rows, err := q.db.QueryContext(ctx, listRecentGrants, limit) if err != nil { return nil, err } defer rows.Close() items := []ListRecentGrantsRow{} for rows.Next() { var i ListRecentGrantsRow if err := rows.Scan( &i.GrantID, &i.ProductID, &i.GrantedToOrgID, &i.GrantedByPersonID, &i.GrantReason, &i.Quantity, &i.CreatedAt, ); err != nil { return nil, err } items = append(items, i) } if err := rows.Close(); err != nil { return nil, err } if err := rows.Err(); err != nil { return nil, err } return items, nil } const revokeGrant = `-- name: RevokeGrant :one UPDATE core.grants SET status = 'revoked', revoked_at = NOW(), revoked_by_person_id = $2, revocation_reason = $3 WHERE grant_id = $1 AND status = 'active' RETURNING grant_id, product_id, granted_to_billing_account_id, granted_to_org_id, granted_to_person_id, granted_by_person_id, grant_reason, description, quantity, valid_from, valid_until, status, revoked_at, revoked_by_person_id, revocation_reason, metadata, created_at, updated_at, extends_grant_id ` type RevokeGrantParams struct { GrantID string `json:"grant_id"` RevokedByPersonID uuid.NullUUID `json:"revoked_by_person_id"` RevocationReason sql.NullString `json:"revocation_reason"` } func (q *Queries) RevokeGrant(ctx context.Context, arg RevokeGrantParams) (Grant, error) { row := q.db.QueryRowContext(ctx, revokeGrant, arg.GrantID, arg.RevokedByPersonID, arg.RevocationReason) var i Grant err := row.Scan( &i.GrantID, &i.ProductID, &i.GrantedToBillingAccountID, &i.GrantedToOrgID, &i.GrantedToPersonID, &i.GrantedByPersonID, &i.GrantReason, &i.Description, &i.Quantity, &i.ValidFrom, &i.ValidUntil, &i.Status, &i.RevokedAt, &i.RevokedByPersonID, &i.RevocationReason, &i.Metadata, &i.CreatedAt, &i.UpdatedAt, &i.ExtendsGrantID, ) return i, err }