ads

package
v1.801.231 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package ads mounts the Hanzo Cloud /v1/ads/* surface: a native-Go, per-org ad-campaign store on Base/SQLite. It is the NET-NEW ads domain built directly on the ONE cloud framework (zip/Fiber + cloud.Deps + per-org SQLite) — the same shape every other in-repo subsystem uses (clients/crm and clients/marketing are the twins), NOT a proxy to a standalone ads pod (there is none — ads.hanzo.ai is net-new).

The Campaign entity is the root of the ad hierarchy (campaign → ad sets → ads): a named campaign on an ad Platform (meta/google/tiktok/x), a lifecycle Status (draft/active/paused/completed), an Objective, and Budget/Spend in minor units (cents). The ad-set and ad legs of the hierarchy are follow-ups that hang off this seam; this is the reviewable domain + campaign CRUD they attach to.

Tenant isolation is enforced SERVER-SIDE on every request: the org is principal.Org(c) — the value SanitizeIdentity minted from the VALIDATED bearer owner claim (HIP-0026) — and NEVER a client-supplied header. Every store query filters WHERE org=?, so one tenant can never read or mutate another's data.

Surface (all org-scoped; /v1 only):

GET    /v1/ads/summary            per-org roll-up (total/active/budget/spend)
GET    /v1/ads/campaigns          list campaigns (?status=)      -> {data:[…]}
POST   /v1/ads/campaigns          create a campaign              -> Campaign (201)
GET    /v1/ads/campaigns/:id      campaign detail                -> Campaign
PUT    /v1/ads/campaigns/:id      update a campaign              -> Campaign
DELETE /v1/ads/campaigns/:id      delete a campaign

serve.go auto-registers GET /v1/ads/health (this subsystem does not set OwnsHealth, so the generic always-ok liveness route serves it).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Mount

func Mount(app *zip.App, deps cloud.Deps) error

Mount wires the ads surface onto app per HIP-0106. It keeps a package global (mounted) for Shutdown, so it constructs the Service value directly — the same "complex flavour" clients/crm uses.

func PaidSpend added in v1.801.186

func PaidSpend(ctx context.Context, org string, ref PaidRef) (int64, error)

PaidSpend reads the provider-reported spend (minor units) for a launched ad campaign. Fail-closed on the token; honest 0 when the platform is unsupported.

func PausePaid added in v1.801.186

func PausePaid(ctx context.Context, org string, ref PaidRef) error

PausePaid pauses a launched ad campaign on its provider. Fail-closed on the token.

func Shutdown

func Shutdown() error

Shutdown closes the ads store. Idempotent.

Types

type Campaign

type Campaign struct {
	ID         string `json:"id"`
	Org        string `json:"-"`
	Name       string `json:"name"`
	Platform   string `json:"platform"`
	Account    string `json:"account,omitempty"`    // provider ad-account ref (Meta act_<id>)
	ExternalID string `json:"externalId,omitempty"` // provider campaign id after a launch
	Status     string `json:"status"`
	Objective  string `json:"objective"`
	Budget     int64  `json:"budget"`
	Spend      int64  `json:"spend"`
	CreatedAt  int64  `json:"createdAt"`
	UpdatedAt  int64  `json:"updatedAt"`
}

Campaign is an org-scoped ad campaign — the root of the ad hierarchy (campaign → ad sets → ads; the ad-set/ad legs hang off this seam as follow-ups). Budget and Spend are minor units (cents). Platform is the ad network (meta/google/tiktok/x); Status is the lifecycle (draft/active/paused/completed) — both validated at the write layer against the fixed vocabularies in ads.go.

type PaidPlan added in v1.801.186

type PaidPlan struct {
	Platform    string
	Account     string // provider ad-account ref (Meta: act_<id> or <id>)
	Name        string
	Objective   string // provider objective enum; defaulted per-provider when empty
	BudgetCents int64
	ScheduleAt  int64
}

PaidPlan is the standalone contract for launching one ad campaign — the campaign paid channel adapts campaign.Plan onto it (apps/wire_seams.go). BudgetCents is the org's own (connector-paid) budget; ScheduleAt an optional start time.

type PaidRef added in v1.801.186

type PaidRef struct {
	Platform   string
	Account    string
	ExternalID string
	Status     string
	Detail     string
}

PaidRef is a launched ad campaign's durable handle: the provider-side id plus the platform/account needed to read spend or pause it.

func LaunchPaid added in v1.801.186

func LaunchPaid(ctx context.Context, org string, p PaidPlan) (PaidRef, error)

LaunchPaid creates the ad campaign on its provider using the org's connector token. Fail-closed: it resolves the token BEFORE any provider call. Meta is executed for real; other connected platforms return errUnsupportedPlatform (the connector is verified, only the provider impl is the remaining gap).

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the ads database. ONE SQLite file ({DataDir}/ads.db) holds every org's records; tenant isolation is the `org` column, enforced on EVERY query. This mirrors clients/crm exactly (the ONE storage pattern). MaxOpenConns(1) serializes writes against the single-writer file.

func (*Store) Close

func (s *Store) Close() error

Close closes the underlying database. Idempotent-safe via sql.DB.

func (*Store) Counts

func (s *Store) Counts(ctx context.Context, org string) (total, active int, budget, spend int64, err error)

Counts returns the per-org campaign roll-up: total campaigns, how many are active, and the summed budget + spend (cents) — a real, non-fabricated summary for the ads module's overview cards.

func (*Store) CreateCampaign

func (s *Store) CreateCampaign(ctx context.Context, c Campaign) (Campaign, error)

func (*Store) DeleteCampaign

func (s *Store) DeleteCampaign(ctx context.Context, org, id string) (bool, error)

func (*Store) GetCampaign

func (s *Store) GetCampaign(ctx context.Context, org, id string) (Campaign, error)

func (*Store) ListCampaigns

func (s *Store) ListCampaigns(ctx context.Context, org, status string, limit int) ([]Campaign, error)

ListCampaigns lists the org's campaigns, optionally filtered by status (status=="" means all). Most-recently-updated first.

func (*Store) MarkLaunched added in v1.801.186

func (s *Store) MarkLaunched(ctx context.Context, org, id, account, externalID string, updatedAt int64) (Campaign, error)

MarkLaunched records the provider execution on a stored campaign: its account + external id, and status=active. Org-scoped — a cross-tenant id affects zero rows (errNotFound), never a foreign mutation. This is the ONLY writer of external_id, so the launch link is never clobbered by a user edit.

func (*Store) UpdateCampaign

func (s *Store) UpdateCampaign(ctx context.Context, c Campaign) (Campaign, error)

UpdateCampaign edits the user-owned fields. external_id is deliberately NOT in the SET list: it is launch-owned (MarkLaunched sets it), so editing a campaign never clobbers the link to its live provider execution.

Jump to

Keyboard shortcuts

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