Archives openspec change slice3-walk-fixes and syncs its five delta specs (fedwiki-sites, entitlements, operator-panel-navigation, operator-list-scale, ui-quality-gate). - FedWiki site usage is read from active site rows in both quota readers; the reservation counter converges on the rows: raise-only after farm sync and inside the create quota check, exact at boot. The understated production counters repair on the first boot. - The People tile caption excludes the reserved system person through the same query parameter the directory uses. - The operator Domains live-claims list is a governed list: pages of 50, true total, search over root name and organization, a pending/active facet. - New lint rule table-without-list-controls refuses an unpaged page-body table unless it carries a list-scale exempt marker with a reason; six curated or detail tables carry one. Its first run caught the operator FedWiki sites list, which is now governed the same way. - Entitlement-set rule copy: "Per unit", "Multiplied by the quantity purchased or granted."
356 lines
10 KiB
Go
356 lines
10 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.29.0
|
|
// source: persons.sql
|
|
|
|
package identity
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
const countActivePersons = `-- name: CountActivePersons :one
|
|
SELECT COUNT(*) FROM core.persons
|
|
WHERE status = 'active'
|
|
`
|
|
|
|
// Operator overview tile: how many people the deployment currently serves.
|
|
// Mirrors LookupPersons' status='active' filter so the headline number and
|
|
// the lookup affordance above it are counting the same population.
|
|
func (q *Queries) CountActivePersons(ctx context.Context) (int64, error) {
|
|
row := q.db.QueryRowContext(ctx, countActivePersons)
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
const countPersonsJoinedLast30Days = `-- name: CountPersonsJoinedLast30Days :one
|
|
SELECT COUNT(*) FROM core.persons
|
|
WHERE status = 'active' AND created_at > now() - interval '30 days'
|
|
AND ($1::uuid IS NULL
|
|
OR person_id <> $1::uuid)
|
|
`
|
|
|
|
// The People tile's caption: velocity rather than a restatement of the
|
|
// census. Same status filter as CountActivePersons so both numbers
|
|
// describe the same population.
|
|
// sqlc.narg(exclude_person_id): the reserved system person, in the shape
|
|
// ListPersonsPage uses, so the caption cannot drift from the headline and
|
|
// the directory total by counting it differently. NULL excludes nothing.
|
|
func (q *Queries) CountPersonsJoinedLast30Days(ctx context.Context, excludePersonID uuid.NullUUID) (int64, error) {
|
|
row := q.db.QueryRowContext(ctx, countPersonsJoinedLast30Days, excludePersonID)
|
|
var count int64
|
|
err := row.Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
const createPerson = `-- name: CreatePerson :one
|
|
INSERT INTO core.persons (user_id, display_name, primary_email, primary_email_verified)
|
|
VALUES ($1, $2, $3, $4)
|
|
RETURNING person_id, user_id, display_name, primary_email, primary_email_verified, status, created_at, updated_at
|
|
`
|
|
|
|
type CreatePersonParams struct {
|
|
UserID string `json:"user_id"`
|
|
DisplayName string `json:"display_name"`
|
|
PrimaryEmail string `json:"primary_email"`
|
|
PrimaryEmailVerified bool `json:"primary_email_verified"`
|
|
}
|
|
|
|
func (q *Queries) CreatePerson(ctx context.Context, arg CreatePersonParams) (Person, error) {
|
|
row := q.db.QueryRowContext(ctx, createPerson,
|
|
arg.UserID,
|
|
arg.DisplayName,
|
|
arg.PrimaryEmail,
|
|
arg.PrimaryEmailVerified,
|
|
)
|
|
var i Person
|
|
err := row.Scan(
|
|
&i.PersonID,
|
|
&i.UserID,
|
|
&i.DisplayName,
|
|
&i.PrimaryEmail,
|
|
&i.PrimaryEmailVerified,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const ensureSystemPerson = `-- name: EnsureSystemPerson :exec
|
|
INSERT INTO core.persons (user_id, display_name, primary_email)
|
|
VALUES ($1, $2, $3)
|
|
ON CONFLICT (user_id) DO NOTHING
|
|
`
|
|
|
|
type EnsureSystemPersonParams struct {
|
|
UserID string `json:"user_id"`
|
|
DisplayName string `json:"display_name"`
|
|
PrimaryEmail string `json:"primary_email"`
|
|
}
|
|
|
|
// Idempotently insert the reserved system person that owns the System tenant
|
|
// (keyed on the unique user_id). Read back with GetPersonByUserID.
|
|
func (q *Queries) EnsureSystemPerson(ctx context.Context, arg EnsureSystemPersonParams) error {
|
|
_, err := q.db.ExecContext(ctx, ensureSystemPerson, arg.UserID, arg.DisplayName, arg.PrimaryEmail)
|
|
return err
|
|
}
|
|
|
|
const getPersonByID = `-- name: GetPersonByID :one
|
|
SELECT person_id, user_id, display_name, primary_email, primary_email_verified, status, created_at, updated_at FROM core.persons
|
|
WHERE person_id = $1
|
|
`
|
|
|
|
func (q *Queries) GetPersonByID(ctx context.Context, personID string) (Person, error) {
|
|
row := q.db.QueryRowContext(ctx, getPersonByID, personID)
|
|
var i Person
|
|
err := row.Scan(
|
|
&i.PersonID,
|
|
&i.UserID,
|
|
&i.DisplayName,
|
|
&i.PrimaryEmail,
|
|
&i.PrimaryEmailVerified,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getPersonByUserID = `-- name: GetPersonByUserID :one
|
|
SELECT person_id, user_id, display_name, primary_email, primary_email_verified, status, created_at, updated_at FROM core.persons
|
|
WHERE user_id = $1
|
|
`
|
|
|
|
func (q *Queries) GetPersonByUserID(ctx context.Context, userID string) (Person, error) {
|
|
row := q.db.QueryRowContext(ctx, getPersonByUserID, userID)
|
|
var i Person
|
|
err := row.Scan(
|
|
&i.PersonID,
|
|
&i.UserID,
|
|
&i.DisplayName,
|
|
&i.PrimaryEmail,
|
|
&i.PrimaryEmailVerified,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listPersons = `-- name: ListPersons :many
|
|
SELECT person_id, user_id, display_name, primary_email, primary_email_verified, status, created_at, updated_at FROM core.persons
|
|
ORDER BY display_name
|
|
`
|
|
|
|
func (q *Queries) ListPersons(ctx context.Context) ([]Person, error) {
|
|
rows, err := q.db.QueryContext(ctx, listPersons)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []Person{}
|
|
for rows.Next() {
|
|
var i Person
|
|
if err := rows.Scan(
|
|
&i.PersonID,
|
|
&i.UserID,
|
|
&i.DisplayName,
|
|
&i.PrimaryEmail,
|
|
&i.PrimaryEmailVerified,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); 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 listPersonsPage = `-- name: ListPersonsPage :many
|
|
SELECT person_id, user_id, display_name, primary_email, primary_email_verified, status, created_at,
|
|
count(*) OVER() AS total_count
|
|
FROM core.persons
|
|
WHERE ($1::uuid IS NULL
|
|
OR person_id <> $1::uuid)
|
|
AND ($2::text IS NULL
|
|
OR display_name ILIKE '%' || $2::text || '%'
|
|
OR primary_email ILIKE '%' || $2::text || '%')
|
|
ORDER BY created_at DESC
|
|
LIMIT $4::int OFFSET $3::int
|
|
`
|
|
|
|
type ListPersonsPageParams struct {
|
|
ExcludePersonID uuid.NullUUID `json:"exclude_person_id"`
|
|
Q sql.NullString `json:"q"`
|
|
PageOffset int32 `json:"page_offset"`
|
|
PageLimit int32 `json:"page_limit"`
|
|
}
|
|
|
|
type ListPersonsPageRow struct {
|
|
PersonID string `json:"person_id"`
|
|
UserID string `json:"user_id"`
|
|
DisplayName string `json:"display_name"`
|
|
PrimaryEmail string `json:"primary_email"`
|
|
PrimaryEmailVerified bool `json:"primary_email_verified"`
|
|
Status string `json:"status"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
TotalCount int64 `json:"total_count"`
|
|
}
|
|
|
|
// People directory operator surface (operator-list-scale UX-4 /
|
|
// operator-people-directory D6): the paged, searched query feeding
|
|
// GET /operator/persons. Ordered newest-joined first so "who joined this
|
|
// week?" is answered by page one.
|
|
//
|
|
// sqlc.narg(q): NULL matches every row; set, a case-insensitive substring
|
|
// match against display_name or primary_email (operator-list-scale:
|
|
// "carries a scoped server-side search" -- "people: display name and
|
|
// email").
|
|
// sqlc.narg(exclude_person_id): the reserved system person (maintainer
|
|
// decision 2026-08-23: infrastructure, never "joined", excluded from the
|
|
// directory and its totals; it stays visible as the System tenant's owner
|
|
// in the organizations context). NULL excludes nothing.
|
|
// count(*) OVER() carries the true total for the filtered set alongside
|
|
// the page's rows (design D2), so the stated total never reflects only
|
|
// the page.
|
|
func (q *Queries) ListPersonsPage(ctx context.Context, arg ListPersonsPageParams) ([]ListPersonsPageRow, error) {
|
|
rows, err := q.db.QueryContext(ctx, listPersonsPage,
|
|
arg.ExcludePersonID,
|
|
arg.Q,
|
|
arg.PageOffset,
|
|
arg.PageLimit,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListPersonsPageRow{}
|
|
for rows.Next() {
|
|
var i ListPersonsPageRow
|
|
if err := rows.Scan(
|
|
&i.PersonID,
|
|
&i.UserID,
|
|
&i.DisplayName,
|
|
&i.PrimaryEmail,
|
|
&i.PrimaryEmailVerified,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&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 lookupPersons = `-- name: LookupPersons :many
|
|
SELECT person_id, display_name, primary_email, status
|
|
FROM core.persons
|
|
WHERE status = 'active'
|
|
AND (primary_email = $1 OR display_name ILIKE '%' || $1 || '%')
|
|
ORDER BY
|
|
CASE WHEN primary_email = $1 THEN 0 ELSE 1 END,
|
|
display_name
|
|
LIMIT 20
|
|
`
|
|
|
|
type LookupPersonsRow struct {
|
|
PersonID string `json:"person_id"`
|
|
DisplayName string `json:"display_name"`
|
|
PrimaryEmail string `json:"primary_email"`
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
// Resolves a lookup term to one or more active persons for the operator
|
|
// landing-surface lookup affordance. Exact email match wins (deterministic
|
|
// — operators using email expect precision); otherwise falls through to
|
|
// case-insensitive substring match against display_name. Status='active'
|
|
// filters out removed accounts. LIMIT 20 caps the disambiguation list
|
|
// without paging.
|
|
func (q *Queries) LookupPersons(ctx context.Context, primaryEmail string) ([]LookupPersonsRow, error) {
|
|
rows, err := q.db.QueryContext(ctx, lookupPersons, primaryEmail)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []LookupPersonsRow{}
|
|
for rows.Next() {
|
|
var i LookupPersonsRow
|
|
if err := rows.Scan(
|
|
&i.PersonID,
|
|
&i.DisplayName,
|
|
&i.PrimaryEmail,
|
|
&i.Status,
|
|
); 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 updatePerson = `-- name: UpdatePerson :one
|
|
UPDATE core.persons
|
|
SET display_name = $1, primary_email = $2, primary_email_verified = $3
|
|
WHERE person_id = $4
|
|
RETURNING person_id, user_id, display_name, primary_email, primary_email_verified, status, created_at, updated_at
|
|
`
|
|
|
|
type UpdatePersonParams struct {
|
|
DisplayName string `json:"display_name"`
|
|
PrimaryEmail string `json:"primary_email"`
|
|
PrimaryEmailVerified bool `json:"primary_email_verified"`
|
|
PersonID string `json:"person_id"`
|
|
}
|
|
|
|
func (q *Queries) UpdatePerson(ctx context.Context, arg UpdatePersonParams) (Person, error) {
|
|
row := q.db.QueryRowContext(ctx, updatePerson,
|
|
arg.DisplayName,
|
|
arg.PrimaryEmail,
|
|
arg.PrimaryEmailVerified,
|
|
arg.PersonID,
|
|
)
|
|
var i Person
|
|
err := row.Scan(
|
|
&i.PersonID,
|
|
&i.UserID,
|
|
&i.DisplayName,
|
|
&i.PrimaryEmail,
|
|
&i.PrimaryEmailVerified,
|
|
&i.Status,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|