clients/

directory
v0.0.41 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2026 License: MIT

Directories

Path Synopsis
Package analytics builds the AnalyticsStore: the zero-infrastructure stub (the default) or the CQL store (Apache Cassandra locally, Amazon Keyspaces in staging, chosen by the nested CQL config).
Package analytics builds the AnalyticsStore: the zero-infrastructure stub (the default) or the CQL store (Apache Cassandra locally, Amazon Keyspaces in staging, chosen by the nested CQL config).
cassandra
Package cassandra is the Cassandra-protocol AnalyticsStore (Apache Cassandra or Amazon Keyspaces behind clients/interfaces.CQLSession).
Package cassandra is the Cassandra-protocol AnalyticsStore (Apache Cassandra or Amazon Keyspaces behind clients/interfaces.CQLSession).
stub
Package stub is the default analytics store: it accepts every write and answers every query with an empty result, so the graph boots with no Cassandra.
Package stub is the default analytics store: it accepts every write and answers every query with an empty result, so the graph boots with no Cassandra.
Package auth0 builds the Auth0Management client from config: the stub (the default), which reaches no tenant, or the Management API (management), run through the client tier (Decorate).
Package auth0 builds the Auth0Management client from config: the stub (the default), which reaches no tenant, or the Management API (management), run through the client tier (Decorate).
management
Package management is the auth0 family's Management API backend: a client-credentials token, minted once and reused until it nears expiry, then the organizations endpoints; and the tenant's public JWKS, which needs no token.
Package management is the auth0 family's Management API backend: a client-credentials token, minted once and reused until it nears expiry, then the organizations endpoints; and the tenant's public JWKS, which needs no token.
stub
Package stub is the auth0 family's zero-infrastructure backend: it reaches no tenant, so every call is CodeUnavailable rather than an empty answer.
Package stub is the auth0 family's zero-infrastructure backend: it reaches no tenant, so every call is CodeUnavailable rather than an empty answer.
aws
account
Package account resolves a named environment to an AWS session verified against the account it must run in: the config is loaded from the ambient credential chain or the env's shared profile, the credentials are retrieved once and pinned, and STS confirms whose they are, so a command can never act with credentials for another account.
Package account resolves a named environment to an AWS session verified against the account it must run in: the config is loaded from the ambient credential chain or the env's shared profile, the credentials are retrieved once and pinned, and STS confirms whose they are, so a command can never act with credentials for another account.
bedrock
Package bedrock builds the Amazon Bedrock runtime client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package bedrock builds the Amazon Bedrock runtime client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
iam
Package iam builds the AWS IAM client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package iam builds the AWS IAM client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
route53
Package route53 builds the Amazon Route 53 client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package route53 builds the Amazon Route 53 client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
secretsmanager
Package secretsmanager builds the AWS Secrets Manager client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package secretsmanager builds the AWS Secrets Manager client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
servicequotas
Package servicequotas builds the AWS Service Quotas client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package servicequotas builds the AWS Service Quotas client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
ses
Package ses builds the Amazon SES (v2) client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package ses builds the Amazon SES (v2) client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
sts
Package sts builds the AWS STS client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package sts builds the AWS STS client from config: the stub (the default) or the AWS SDK client over an injected aws.Config (sdk), run through the client tier (Decorate).
Package cache builds a ByteCache from config: the always-miss stub (the default) or Redis.
Package cache builds a ByteCache from config: the always-miss stub (the default) or Redis.
redis
Package redis provides a Redis-backed cache implementation with singleflight support.
Package redis provides a Redis-backed cache implementation with singleflight support.
stub
Package stub is the zero-infrastructure ByteCache: every Get misses and every write is dropped, so a graph boots and runs uncached without Redis.
Package stub is the zero-infrastructure ByteCache: every Get misses and every write is dropped, so a graph boots and runs uncached without Redis.
Package chaos builds the fault injector from config: the stub (the default), which injects nothing, or chaos-mesh, which creates and deletes Chaos Mesh custom resources with kubectl, run through the client tier (Decorate).
Package chaos builds the fault injector from config: the stub (the default), which injects nothing, or chaos-mesh, which creates and deletes Chaos Mesh custom resources with kubectl, run through the client tier (Decorate).
Package client is the client tier: the one decoration every outbound client (an SDK, a datastore, an HTTP API) runs its operations through.
Package client is the client tier: the one decoration every outbound client (an SDK, a datastore, an HTTP API) runs its operations through.
Package codebase builds a Codebase from config: the in-memory kind (the default), a plain directory, or a git working tree, each composed with the foundation/codebase views and run through the client tier (Decorate).
Package codebase builds a Codebase from config: the in-memory kind (the default), a plain directory, or a git working tree, each composed with the foundation/codebase views and run through the client tier (Decorate).
fs
Package fs is the plain-directory CodebaseSource: every file under a root, except the `.git` directory, with no version control.
Package fs is the plain-directory CodebaseSource: every file under a root, except the `.git` directory, with no version control.
git
Package git is the git working-tree CodebaseSource: the files git tracks plus the untracked files it does not ignore, read from disk, with Changed answered by `git diff --merge-base`.
Package git is the git working-tree CodebaseSource: the files git tracks plus the untracked files it does not ignore, read from disk, with Changed answered by `git diff --merge-base`.
memory
Package memory is the in-memory CodebaseSource: a map of root-relative paths to contents, with no version control.
Package memory is the in-memory CodebaseSource: a map of root-relative paths to contents, with no version control.
Package connector builds ConnectorSources for the connector family: S3 now, a future GDrive/Salesforce kind added as a kinds-table entry + sibling package (ARCHITECTURE.md#the-one-idea).
Package connector builds ConnectorSources for the connector family: S3 now, a future GDrive/Salesforce kind added as a kinds-table entry + sibling package (ARCHITECTURE.md#the-one-idea).
s3
Package s3 implements the S3 ConnectorSource for the connector family: a "test connection" probe that lists a bounded page under a connector's bucket/prefix using the connector's OWN credentials, over the shared StorageClient (INJECTED — this package never imports go/clients/storage, so there is no lateral same-layer import).
Package s3 implements the S3 ConnectorSource for the connector family: a "test connection" probe that lists a bounded page under a connector's bucket/prefix using the connector's OWN credentials, over the shared StorageClient (INJECTED — this package never imports go/clients/storage, so there is no lateral same-layer import).
cql
Package cql builds a CQL (Cassandra-protocol) Session — self-managed Apache Cassandra (KindCassandra, local and dev) or Amazon Keyspaces (KindKeyspaces, staging) — behind the consumer-side Session seam, so the choice is a config change.
Package cql builds a CQL (Cassandra-protocol) Session — self-managed Apache Cassandra (KindCassandra, local and dev) or Amazon Keyspaces (KindKeyspaces, staging) — behind the consumer-side Session seam, so the choice is a config change.
cassandra
Package cassandra is the self-managed Apache Cassandra kind of clients/cql (local Compose, dev): a token-aware, DC-aware host policy, optional password auth and TLS, and speculative execution on idempotent reads.
Package cassandra is the self-managed Apache Cassandra kind of clients/cql (local Compose, dev): a token-aware, DC-aware host policy, optional password auth and TLS, and speculative execution on idempotent reads.
driver
Package driver adapts the gocql driver to the CQLSession contract: Dial opens a session on a cluster configuration (built by a cql kind's subpackage), and every driver error is coded at this boundary.
Package driver adapts the gocql driver to the CQLSession contract: Dial opens a session on a cluster configuration (built by a cql kind's subpackage), and every driver error is coded at this boundary.
keyspaces
Package keyspaces is the Amazon Keyspaces kind of clients/cql: the regional endpoint on port 9142, mandatory TLS with host verification, SigV4 authentication (the AWS SigV4 gocql plugin, credentials from an AWS credentials provider — the default chain, IRSA in-cluster) and DisableInitialHostLookup, per AWS guidance.
Package keyspaces is the Amazon Keyspaces kind of clients/cql: the regional endpoint on port 9142, mandatory TLS with host verification, SigV4 authentication (the AWS SigV4 gocql plugin, credentials from an AWS credentials provider — the default chain, IRSA in-cluster) and DisableInitialHostLookup, per AWS guidance.
Package database builds the SQL connection pool from config: PostgreSQL (postgres/) today, behind interfaces.DatabasePool, so switching engines is a config change.
Package database builds the SQL connection pool from config: PostgreSQL (postgres/) today, behind interfaces.DatabasePool, so switching engines is a config change.
postgres
Package postgres is the PostgreSQL backend of the database client tier: a lifecycle-managed *sql.DB pool (Client) plus ORM-independent pool utilities — a boot-time reachability probe (Ping) and a Prometheus pool-stats collector.
Package postgres is the PostgreSQL backend of the database client tier: a lifecycle-managed *sql.DB pool (Client) plus ORM-independent pool utilities — a boot-time reachability probe (Ping) and a Prometheus pool-stats collector.
Package docker builds the DockerClient from config: the stub (the default) or the docker binary run through a CommandRunner (exec), run through the client tier (Decorate).
Package docker builds the DockerClient from config: the stub (the default) or the docker binary run through a CommandRunner (exec), run through the client tier (Decorate).
exec
Package exec is the DockerClient that runs the docker binary through a CommandRunner.
Package exec is the DockerClient that runs the docker binary through a CommandRunner.
stub
Package stub is the DockerClient with no daemon: builds, pushes and stacks succeed without effect, and no image exists.
Package stub is the DockerClient with no daemon: builds, pushes and stacks succeed without effect, and no image exists.
git
Package git builds the GitClient from config: the stub (the default) or the git binary run through a CommandRunner (exec), run through the client tier (Decorate).
Package git builds the GitClient from config: the stub (the default) or the git binary run through a CommandRunner (exec), run through the client tier (Decorate).
exec
Package exec is the GitClient that runs the git binary through a CommandRunner.
Package exec is the GitClient that runs the git binary through a CommandRunner.
stub
Package stub is the GitClient that touches nothing: every listing is empty, nothing has changed, and no directory is a repository.
Package stub is the GitClient that touches nothing: every listing is empty, nothing has changed, and no directory is a repository.
Package helm builds the HelmClient from config: the stub (the default) or the helm binary run through a CommandRunner (exec), run through the client tier (Decorate), and adapts a HelmClient to the Renderer a Codebase renders charts with.
Package helm builds the HelmClient from config: the stub (the default) or the helm binary run through a CommandRunner (exec), run through the client tier (Decorate), and adapts a HelmClient to the Renderer a Codebase renders charts with.
exec
Package exec is the HelmClient that runs the helm binary through a CommandRunner.
Package exec is the HelmClient that runs the helm binary through a CommandRunner.
stub
Package stub is the HelmClient that renders nothing and fetches nothing.
Package stub is the HelmClient that renders nothing and fetches nothing.
jobs
river
Package river is the River job-queue client: the worker Runtime (pool + work loop), the InsertClient that enqueues from outside a worker, and Migrate for River's schema.
Package river is the River job-queue client: the worker Runtime (pool + work loop), the InsertClient that enqueues from outside a worker, and Migrate for River's schema.
Package kubectl builds the KubectlClient from config: the stub (the default) or the kubectl binary run through a CommandRunner (exec), run through the client tier (Decorate).
Package kubectl builds the KubectlClient from config: the stub (the default) or the kubectl binary run through a CommandRunner (exec), run through the client tier (Decorate).
exec
Package exec is the KubectlClient that runs the kubectl binary through a CommandRunner.
Package exec is the KubectlClient that runs the kubectl binary through a CommandRunner.
stub
Package stub is the KubectlClient with no cluster: reads return empty lists and writes that name files succeed without effect.
Package stub is the KubectlClient with no cluster: reads return empty lists and writes that name files succeed without effect.
Package lock builds a config-selected core/interfaces.Locker — a DistributedLock (keyed, token-fenced, best-effort) plus Hold, the managed acquire-with-watchdog helper a single-active-operation guard depends on.
Package lock builds a config-selected core/interfaces.Locker — a DistributedLock (keyed, token-fenced, best-effort) plus Hold, the managed acquire-with-watchdog helper a single-active-operation guard depends on.
local
Package local provides an in-process DistributedLock backend for single-pod deployments (dev / replica=1), where cross-process coordination is unnecessary.
Package local provides an in-process DistributedLock backend for single-pod deployments (dev / replica=1), where cross-process coordination is unnecessary.
redis
Package redis provides a cross-pod DistributedLock backend over Redis, for multi-replica deployments (staging/prod).
Package redis provides a cross-pod DistributedLock backend over Redis, for multi-replica deployments (staging/prod).
Package messaging builds the message publisher and consumer from config: the in-process memory broker (the default), SQS, or Redis Pub/Sub.
Package messaging builds the message publisher and consumer from config: the in-process memory broker (the default), SQS, or Redis Pub/Sub.
memory
Package memory provides an in-process messaging backend for no-infra builds and tests.
Package memory provides an in-process messaging backend for no-infra builds and tests.
redis
Package redis provides a Redis Pub/Sub messaging integration (publisher + subscriber) implementing the core MessagePublisher / MessageConsumer contracts over PUBLISH / SUBSCRIBE / PSUBSCRIBE.
Package redis provides a Redis Pub/Sub messaging integration (publisher + subscriber) implementing the core MessagePublisher / MessageConsumer contracts over PUBLISH / SUBSCRIBE / PSUBSCRIBE.
sqs
Package sqs provides an AWS-SDK-backed SQS messaging integration (publisher + subscriber) usable against real AWS SQS and against ElasticMQ for local dev.
Package sqs provides an AWS-SDK-backed SQS messaging integration (publisher + subscriber) usable against real AWS SQS and against ElasticMQ for local dev.
Package outbox builds the OutboxSink a transactional-outbox relay delivers through: the zero-infrastructure stub (the default), an SQS queue, or an S3 bucket, selected by Kind.
Package outbox builds the OutboxSink a transactional-outbox relay delivers through: the zero-infrastructure stub (the default), an SQS queue, or an S3 bucket, selected by Kind.
s3
Package s3 is the S3 OutboxSink: it writes each record as one object, keyed by a template, with a SHA-256 integrity checksum (Object Lock buckets require an integrity checksum and accept it in place of Content-MD5) and SSE-KMS when the record names a key.
Package s3 is the S3 OutboxSink: it writes each record as one object, keyed by a template, with a SHA-256 integrity checksum (Object Lock buckets require an integrity checksum and accept it in place of Content-MD5) and SSE-KMS when the record names a key.
sqs
Package sqs is the SQS OutboxSink: it routes each record to a queue, sends each queue's records with SendMessageBatch (at most 10 per request and 1 MiB of messages) and maps each entry's result back to its record.
Package sqs is the SQS OutboxSink: it routes each record to a queue, sends each queue's records with SendMessageBatch (at most 10 per request and 1 MiB of messages) and maps each entry's result back to its record.
stub
Package stub is the zero-infrastructure OutboxSink: it accepts every record and delivers nothing, so the graph boots with no queue or bucket.
Package stub is the zero-infrastructure OutboxSink: it accepts every record and delivers nothing, so the graph boots with no queue or bucket.
Package planstore builds the saved-plan store from config: local (the default), which leaves the plans where they were written, or object, which keeps them in an object store behind a SHA-256 manifest so a later job on another machine applies exactly them.
Package planstore builds the saved-plan store from config: local (the default), which leaves the plans where they were written, or object, which keeps them in an object store behind a SHA-256 manifest so a later job on another machine applies exactly them.
Package process builds the Supervisor from config: the stub (the default; starts nothing) or real operating-system processes (exec).
Package process builds the Supervisor from config: the stub (the default; starts nothing) or real operating-system processes (exec).
exec
Package exec is the Supervisor that runs real operating-system processes.
Package exec is the Supervisor that runs real operating-system processes.
stub
Package stub is the Supervisor that starts nothing: every process is ready at once and exits cleanly when stopped.
Package stub is the Supervisor that starts nothing: every process is ready at once and exits cleanly when stopped.
Package prometheus builds the MetricsQuerier from config: the zero-infrastructure stub (the default) or the HTTP query API, its requests run through the client tier.
Package prometheus builds the MetricsQuerier from config: the zero-infrastructure stub (the default) or the HTTP query API, its requests run through the client tier.
http
Package http is the HTTP backend of the Prometheus querier: instant queries reduced to one sample, and range queries reduced to one series, over a Prometheus server's HTTP query API.
Package http is the HTTP backend of the Prometheus querier: instant queries reduced to one sample, and range queries reduced to one series, over a Prometheus server's HTTP query API.
stub
Package stub is the zero-infrastructure metrics querier: every instant query is 0 and every range query an empty series, with no network I/O.
Package stub is the zero-infrastructure metrics querier: every instant query is 0 and every range query an empty series, with no network I/O.
Package prompt builds the Prompter from config: deny (the default), which refuses every question for a front-end with no operator, or tty, which asks an operator through injected streams, so a capability never reads process stdin.
Package prompt builds the Prompter from config: deny (the default), which refuses every question for a front-end with no operator, or tty, which asks an operator through injected streams, so a capability never reads process stdin.
deny
Package deny is the Prompter backend for a front-end with no operator (an MCP server, a web app, CI): it refuses every question with the --yes guidance instead of blocking.
Package deny is the Prompter backend for a front-end with no operator (an MCP server, a web app, CI): it refuses every question with the --yes guidance instead of blocking.
tty
Package tty is the interactive Prompter backend: it writes the question to an injected writer and reads a y/N answer from an injected reader.
Package tty is the interactive Prompter backend: it writes the question to an injected writer and reads a y/N answer from an injected reader.
Package replaybuffer builds a ReplayBuffer from config — the in-process memory buffer (single pod; the default) or Redis (cross-pod) — and runs it through the client tier (Decorate).
Package replaybuffer builds a ReplayBuffer from config — the in-process memory buffer (single pod; the default) or Redis (cross-pod) — and runs it through the client tier (Decorate).
memory
Package memory provides an in-process ReplayBuffer backend for single-pod deployments (dev / replica=1), where a reconnect lands on the same pod so cross-pod sharing is unnecessary.
Package memory provides an in-process ReplayBuffer backend for single-pod deployments (dev / replica=1), where a reconnect lands on the same pod so cross-pod sharing is unnecessary.
redis
Package redis provides a cross-pod ReplayBuffer backend over Redis, for multi-replica deployments (staging/prod) where a reconnect may land on a different pod than the one that buffered the tail.
Package redis provides a cross-pod ReplayBuffer backend over Redis, for multi-replica deployments (staging/prod) where a reconnect may land on a different pod than the one that buffered the tail.
rpc
Package rpc builds the RPC client from config: gRPC (grpc/) today, behind RPCClient, so switching RPC frameworks is a config change.
Package rpc builds the RPC client from config: gRPC (grpc/) today, behind RPCClient, so switching RPC frameworks is a config change.
connect/interceptors
Package interceptors runs a generated Connect client's calls through the client tier (client.Tier): ClientOptions installs it as a Connect client interceptor.
Package interceptors runs a generated Connect client's calls through the client tier (client.Tier): ClientOptions installs it as a Connect client interceptor.
grpc
Package grpc dials gRPC client connections: NewClient builds one, and Client manages it as a lifecycle-managed, health-checkable client (interfaces.Client).
Package grpc dials gRPC client connections: NewClient builds one, and Client manages it as a lifecycle-managed, health-checkable client (interfaces.Client).
grpc/interceptors
Package interceptors runs a gRPC client connection's calls through the client tier (client.Tier): ClientOptions installs it as dial options, carrying the trace context and the service token on every call.
Package interceptors runs a gRPC client connection's calls through the client tier (client.Tier): ClientOptions installs it as dial options, carrying the trace context and the service token on every call.
wire
Package wire is the codec between RPC status codes (Connect and gRPC share one code space) and the domain's apperr codes.
Package wire is the codec between RPC status codes (Connect and gRPC share one code space) and the domain's apperr codes.
Package secrets is the credential-source client tier: it selects a secret backend — an environment variable (env/), a git-ignored local file (file/), or AWS Secrets Manager (awssm/) — by Kind (env when empty) and returns the interfaces.Source contract, so switching where a credential is read is a configuration change, not a caller edit.
Package secrets is the credential-source client tier: it selects a secret backend — an environment variable (env/), a git-ignored local file (file/), or AWS Secrets Manager (awssm/) — by Kind (env when empty) and returns the interfaces.Source contract, so switching where a credential is read is a configuration change, not a caller edit.
awssm
Package awssm implements the AWS Secrets Manager credential Source: it reads a credential from a Secrets Manager secret (a JSON object) named by a caller-supplied Ref→location mapping, extracting the configured JSON field.
Package awssm implements the AWS Secrets Manager credential Source: it reads a credential from a Secrets Manager secret (a JSON object) named by a caller-supplied Ref→location mapping, extracting the configured JSON field.
env
Package env implements the environment-variable credential Source: it resolves a Ref to a configured environment variable name and reads its value via os.Getenv.
Package env implements the environment-variable credential Source: it resolves a Ref to a configured environment variable name and reads its value via os.Getenv.
file
Package file implements the file-backed credential Source: it reads and writes credentials in a git-ignored local file (a dotenv-style KEY=value store) named by a caller-supplied Ref→location mapping.
Package file implements the file-backed credential Source: it reads and writes credentials in a git-ignored local file (a dotenv-style KEY=value store) named by a caller-supplied Ref→location mapping.
Package session resolves a credential from a secrets Source, verifies it once, and projects it into the environment a command runs with: the session a CLI command opens before it calls a cloud or an identity provider.
Package session resolves a credential from a secrets Source, verifies it once, and projects it into the environment a command runs with: the session a CLI command opens before it calls a cloud or an identity provider.
Package storage builds the StorageClient from config: the in-memory backend (the default) or an S3-compatible one (AWS S3 or MinIO), run through the client tier (Decorate).
Package storage builds the StorageClient from config: the in-memory backend (the default) or an S3-compatible one (AWS S3 or MinIO), run through the client tier (Decorate).
memory
Package memory provides an in-memory StorageClient backend for no-infra builds and tests.
Package memory provides an in-memory StorageClient backend for no-infra builds and tests.
s3
Package s3 implements the StorageClient against S3-compatible object stores (AWS S3 and MinIO), selected by configuration.
Package s3 implements the StorageClient against S3-compatible object stores (AWS S3 and MinIO), selected by configuration.
Package terraform builds the TerraformClient from config: the stub (the default) or the terraform binary run through a CommandRunner (exec), run through the client tier (Decorate).
Package terraform builds the TerraformClient from config: the stub (the default) or the terraform binary run through a CommandRunner (exec), run through the client tier (Decorate).
exec
Package exec is the TerraformClient that runs the terraform binary through a CommandRunner.
Package exec is the TerraformClient that runs the terraform binary through a CommandRunner.
stub
Package stub is the TerraformClient that plans no changes and applies nothing.
Package stub is the TerraformClient that plans no changes and applies nothing.
Package toolchain owns a developer tool chain's lifecycle, projected from one list of types.ToolEntry values (a tool manifest the consumer loads and checks with types.ValidateToolEntries; the manifest's schema lives in core/types so a foundation-tier manifest can hold it).
Package toolchain owns a developer tool chain's lifecycle, projected from one list of types.ToolEntry values (a tool manifest the consumer loads and checks with types.ValidateToolEntries; the manifest's schema lives in core/types so a foundation-tier manifest can hold it).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL