Documentation
¶
Overview ¶
Package facade4datatug holds the DataTug extension's application commands.
It is storage-agnostic by construction: the only persistence API it uses is dal-go, so it never learns whether the host backs it with Firestore, an in-memory database (tests), or anything else. Platform needs arrive through ports declared in ports.go.
Index ¶
- Variables
- func ValidatePlanConfig(config PlanConfig) error
- type AccountPlanEffect
- type AccountPlanWriter
- type AdmissionReader
- type AdmissionState
- type CallerAdmissionReader
- type ConfiguredProLimits
- type Facade
- type FirstAdmittedMonthReader
- type IDGenerator
- type PaidMonthAllocator
- type PersonalAccount
- type PersonalAccountDirectory
- type PersonalPlanOwnerPort
- type PersonalPlanService
- type PlanAI
- type PlanAccount
- type PlanApplyOutcome
- type PlanClock
- type PlanConfig
- type PlanConfigReader
- type PlanEffectAuthority
- type PlanEffectGrants
- type PlanEffectOwnerPort
- type PlanFacts
- type PlanModel
- type PlanMoneyFence
- type PlanOwnerFence
- type PlanPayment
- type PlanPaymentLine
- type PlanReader
- type PlanRefund
- type PlanResponse
- type PlanStateResult
- type PlanToday
- type ProLimitsResolver
- type ProLimitsSnapshot
- type PurchaseReadiness
- type PurchaseReadinessRequest
- type RegisterGithubProjectRequest
- type ServiceRefundProof
- type UsageReader
Constants ¶
This section is empty.
Variables ¶
var ( // ErrOrgRequired is returned when a GitHub project is registered without // its repository owner. ErrOrgRequired = errors.New("github org is required") // ErrRepoRequired is returned when a GitHub project is registered without // its repository name. ErrRepoRequired = errors.New("github repo is required") )
var ( ErrForeignAccount = errors.New("account is not the caller's personal account") )
var ( // ErrUserIDRequired is returned when a command is called without a user. ErrUserIDRequired = errors.New("user id is required") // ErrTitleRequired is returned when a project is created without a title. ErrTitleRequired = errors.New("project title is required") // ErrUnsupportedStore is returned for a store this API does not serve. A // project in a GitHub repo is created by the client holding the user's // GitHub credential, and a local filesystem project by the datatug CLI // agent — only the DataTug cloud store is created here. ErrUnsupportedStore = errors.New("store is not served by the DataTug cloud API") )
var ErrPlanEffectUnproved = errors.New("plan effect is not proved")
Functions ¶
func ValidatePlanConfig ¶ added in v0.7.0
func ValidatePlanConfig(config PlanConfig) error
ValidatePlanConfig checks the shared plan settings before they are used for plan reads, purchase readiness, or checkout activation.
Types ¶
type AccountPlanEffect ¶ added in v0.5.0
type AccountPlanEffect struct {
Fence PlanOwnerFence
BuyerID string
AccountKind string
PlanID string
Tier string
Period string
Status string
LastPaidEnd time.Time
ScheduledEnd time.Time
EffectiveEnd time.Time
PaidService bool
AppliedPercent int
LaunchGrant bool
Grants PlanEffectGrants
Payments []PlanPayment
CashBasisKnown bool
MoneyIngestEpoch int64
ObservedAt time.Time
CheckoutStartedAt time.Time
QuoteKey string
PaidServiceProofID string
BasisOnly bool
SourceSubscriptionID string
SourceRevision int64
SourcePaidService bool
SourceQuoteKey string
SourcePaidServiceProofID string
LastServiceRefund *ServiceRefundProof
TerminalFullRefund bool `json:"terminalFullRefund,omitempty"`
}
AccountPlanEffect is a provider-neutral copy of the accepted payment fact. The host passes the *complete* source fact to VerifyCurrentEffect and ReconcileMoney; this type never substitutes for paymentus's accepted digest.
type AccountPlanWriter ¶ added in v0.5.0
type AccountPlanWriter struct {
DB dal.DB
Owner PlanEffectOwnerPort
Personal PersonalPlanOwnerPort
Allocator PaidMonthAllocator
Limits ProLimitsResolver
Clock PlanClock
}
AccountPlanWriter is the DataTug domain writer. Its ports are bound by the host to one DAL database; no provider or cross-extension package is imported.
func (AccountPlanWriter) Apply ¶ added in v0.5.0
func (w AccountPlanWriter) Apply(ctx context.Context, effect AccountPlanEffect) (PlanApplyOutcome, error)
type AdmissionReader ¶ added in v0.4.0
type AdmissionState ¶ added in v0.4.0
AdmissionState supplies guards that are authoritative outside this module. Blocked is empty, daily, free_budget, or unverified.
type CallerAdmissionReader ¶ added in v0.6.0
type CallerAdmissionReader interface {
ReadAdmissionForCaller(context.Context, string, string, time.Time) (AdmissionState, error)
}
CallerAdmissionReader lets the host read admission for the authenticated caller and the personal account already proved by PersonalAccountDirectory. The implementation must supply the actual daily count, not a placeholder.
type ConfiguredProLimits ¶ added in v0.5.0
type ConfiguredProLimits struct {
ByPlanID map[string]ProLimitsSnapshot
}
ConfiguredProLimits is a pure, versioned source of complete Pro grants. Production values are supplied by the host's reviewed configuration.
func (ConfiguredProLimits) ResolveProLimits ¶ added in v0.5.0
func (c ConfiguredProLimits) ResolveProLimits(planID string, grants PlanEffectGrants) (ProLimitsSnapshot, error)
type Facade ¶
type Facade struct {
// contains filtered or unexported fields
}
Facade carries the injected database and ports for the DataTug extension's application commands. The host constructs one Facade at composition time (sneat-go/pkg/modules/datatug), wiring a real adapter per port; tests construct it over an in-memory database with fakes.
func NewFacade ¶
func NewFacade(db dal.DB, ids IDGenerator) Facade
NewFacade returns a Facade over the given database and ports.
func (Facade) CreateProject ¶
func (f Facade) CreateProject( ctx context.Context, userID, storeID, title string, ) (projectID string, err error)
CreateProject creates a DataTug project in the cloud store and registers its brief in the user's DataTug index, both in one transaction. It returns the id of the created project.
func (Facade) RegisterGithubProject ¶ added in v0.2.0
func (f Facade) RegisterGithubProject( ctx context.Context, userID string, request RegisterGithubProjectRequest, ) (projectID string, err error)
RegisterGithubProject records a project that lives in a GitHub repository in the user's DataTug index, so it shows up among the user's projects.
The project files themselves are created by the client that holds the user's GitHub credential — this command only keeps the index; the cloud never talks to GitHub. It returns the project id the web client addresses the project by (`repo@org@folder`).
type FirstAdmittedMonthReader ¶ added in v0.4.0
type FirstAdmittedMonthReader interface {
ReadFirstAdmittedMonth(context.Context, string, string, string) (string, error)
}
FirstAdmittedMonthReader reads the same immutable, server-only first-admission marker used by the AI meter. Empty means no question has been admitted yet. It is keyed by product and caller, with the proved personal account included so the host can reject a mismatched binding.
type IDGenerator ¶
type IDGenerator interface {
// NewID returns the id of a new record.
NewID(ctx context.Context) (string, error)
}
IDGenerator is a PORT: the module must not import sneat-go-core, sneat-core-modules or another extension's backend, so anything it needs from outside crosses a small interface defined here and is satisfied by an adapter in the host composition root (sneat-go/pkg/modules/datatug/adapters.go). Domain tests fake the port — see facade_test.go's fakeIDGenerator.
type PaidMonthAllocator ¶ added in v0.5.0
type PaidMonthAllocator interface {
AllocatePaidMonths(PlanPayment, string) (map[string]int64, error)
}
PaidMonthAllocator is a narrow host translation to core's existing AllocatePaidMonths. The writer owns deduplication and aggregation.
type PersonalAccount ¶ added in v0.4.0
type PersonalAccount struct{ ID, Title string }
PersonalAccount is an ownership assertion made by the host directory.
func ResolvePersonalPayer ¶ added in v0.4.0
func ResolvePersonalPayer(ctx context.Context, callerID, accountHint string, directory PersonalAccountDirectory) (PersonalAccount, error)
PersonalPayer is shared by plan reads and the later AI adapter. A foreign account hint is refused before any plan or usage read for that hint.
type PersonalAccountDirectory ¶ added in v0.4.0
type PersonalAccountDirectory interface {
PersonalAccount(context.Context, string) (PersonalAccount, error)
}
PersonalAccountDirectory must prove ownership and provision the personal account through the host. This domain never infers an account from a user ID.
type PersonalPlanOwnerPort ¶ added in v0.5.0
type PersonalPlanService ¶ added in v0.4.0
type PersonalPlanService struct {
Directory PersonalAccountDirectory
Plans PlanReader
Usage UsageReader
Admission AdmissionReader
// CallerAdmission takes precedence when bound. Admission remains supported
// for existing consumers; a new host must bind this caller-aware port.
CallerAdmission CallerAdmissionReader
Config PlanConfigReader
Clock PlanClock
FirstMonth FirstAdmittedMonthReader
}
PersonalPlanService composes ports without depending on transport or store.
func (PersonalPlanService) Read ¶ added in v0.4.0
func (s PersonalPlanService) Read(ctx context.Context, callerID, accountHint, _ string) (PlanResponse, error)
type PlanAI ¶ added in v0.4.0
type PlanAI struct {
Unit string `json:"unit"`
Enforced bool `json:"enforced"`
PeriodID string `json:"periodId"`
Used int64 `json:"used"`
Limit int64 `json:"limit"`
Left int64 `json:"left"`
ResetsAt time.Time `json:"resetsAt"`
Today PlanToday `json:"today"`
Blocked *string `json:"blocked"`
Models []PlanModel `json:"models"`
}
type PlanAccount ¶ added in v0.4.0
type PlanApplyOutcome ¶ added in v0.5.0
type PlanApplyOutcome string
const ( PlanApplied PlanApplyOutcome = "applied" PlanIdempotent PlanApplyOutcome = "idempotent" PlanObsolete PlanApplyOutcome = "obsolete" )
type PlanConfig ¶ added in v0.4.0
type PlanConfig struct {
FreeFirstMonthLimits models4datatug.PlanLimits
FreeLaterMonthLimits models4datatug.PlanLimits
ProLimits models4datatug.PlanLimits
FreeModels []PlanModel
ProModels []PlanModel
DailyLimit int64
ActiveGrace time.Duration
PastDueGrace time.Duration
Enforced bool
UpgradeURL string
ManageURL string
SupportEmail string
}
PlanConfig is supplied by the host, rather than encoded in plan policy. The two Free grants differ by the month of the first admitted question, which is independently read from the meter's server-only marker.
type PlanConfigReader ¶ added in v0.4.0
type PlanConfigReader interface {
ReadPlanConfig(context.Context, string, time.Time) (PlanConfig, error)
}
PlanConfigReader receives the proved account and the one UTC instant sampled for this response; settings can change at runtime without implicit context.
type PlanEffectAuthority ¶ added in v0.5.0
type PlanEffectAuthority string
const ( PlanEffectCurrent PlanEffectAuthority = "current" PlanEffectObsolete PlanEffectAuthority = "obsolete" PlanEffectUnproved PlanEffectAuthority = "unproved" )
type PlanEffectGrants ¶ added in v0.5.0
type PlanEffectGrants struct {
Contributors, ProjectContributors, AIQuestions int64
AIPaysFor string
ProtectedProjects *int64 `json:"protectedProjects,omitempty"`
ProtectedProjectUsers *int64 `json:"protectedProjectUsers,omitempty"`
}
PlanEffectGrants mirrors the values frozen by the payment effect. The protected pair is optional only for accepted legacy effects; complete Pro limits still require a separately versioned server configuration.
type PlanEffectOwnerPort ¶ added in v0.5.0
type PlanEffectOwnerPort interface {
ReadOwner(context.Context, dal.ReadTransaction, string, string, string) (PlanOwnerFence, error)
ReadMoneyFence(context.Context, dal.ReadTransaction, string, string, string) (PlanMoneyFence, error)
ClassifyEffect(context.Context, dal.ReadTransaction, PlanOwnerFence) (PlanEffectAuthority, error)
VerifyCurrentEffect(context.Context, dal.ReadTransaction, AccountPlanEffect) error
ReconcileMoney(context.Context, dal.ReadwriteTransaction, AccountPlanEffect) error
}
PlanEffectOwnerPort is bound to paymentus's transaction-aware owner reader. Every method receives the same DAL transaction as the product writer.
type PlanFacts ¶ added in v0.4.0
type PlanFacts struct {
AccountKind string `json:"accountKind"`
Tier string `json:"tier"`
Period string `json:"period"`
ProviderStatus string `json:"providerStatus"`
PaidUntil *time.Time `json:"paidUntil,omitempty"`
EndsAt *time.Time `json:"endsAt,omitempty"`
LastInvoiceRefundedInFull bool `json:"lastInvoiceRefundedInFull"`
TerminalFullRefund bool `json:"terminalFullRefund,omitempty"`
RefundedAt *time.Time `json:"refundedAt,omitempty"`
FirstPaidAt *time.Time `json:"firstPaidAt,omitempty"`
Founding bool `json:"founding"`
Grants *models4datatug.PlanLimits `json:"grants,omitempty"`
}
PlanFacts are plain, provider-independent inputs to the plan-state mapping.
type PlanMoneyFence ¶ added in v0.5.0
type PlanOwnerFence ¶ added in v0.5.0
type PlanOwnerFence struct {
Mode, Family, AccountID, OwnerSubscriptionID string
OwnerGeneration, SubscriptionRevision int64
}
PlanOwnerFence is copied from the private payment owner tuple by the host.
type PlanPayment ¶ added in v0.5.0
type PlanPayment struct {
Mode, Provider, InvoiceID, PaymentID, SubscriptionID, AccountID string
Currency string
ReceivedCents int64
CashConfirmed, RefundsKnown, DisputeResolved bool
Lines []PlanPaymentLine
Refunds []PlanRefund
}
type PlanPaymentLine ¶ added in v0.5.0
type PlanReader ¶ added in v0.4.0
type PlanReader interface {
ReadCurrentPlan(context.Context, string) (*models4datatug.PlanRecord, error)
}
PlanReader reads only plan/current; an unreadable record falls toward Free.
type PlanRefund ¶ added in v0.5.0
type PlanResponse ¶ added in v0.4.0
type PlanResponse struct {
V int `json:"v"`
Payer string `json:"payer"`
AccountID string `json:"accountId"`
AccountTitle string `json:"accountTitle"`
Role string `json:"role"`
Plan string `json:"plan"`
EffectivePlan string `json:"effectivePlan"`
Status string `json:"status"`
Period string `json:"period"`
PaidUntil *time.Time `json:"paidUntil,omitempty"`
Founding bool `json:"founding"`
Limits models4datatug.PlanLimits `json:"limits"`
AI PlanAI `json:"ai"`
OwnKeyWorks bool `json:"ownKeyWorks"`
CanUpgrade bool `json:"canUpgrade"`
UpgradeURL string `json:"upgradeUrl"`
ManageURL string `json:"manageUrl,omitempty"`
SupportEmail string `json:"supportEmail,omitempty"`
Accounts []PlanAccount `json:"accounts"`
}
type PlanStateResult ¶ added in v0.4.0
type PlanStateResult struct {
Outcome string `json:"outcome"`
Reason string `json:"reason,omitempty"`
Record *models4datatug.PlanRecord `json:"record,omitempty"`
}
PlanStateResult names a write, leave, or refusal. The writer retains the previous aiExtraQuestions and stamps updatedAt outside this pure function.
func PlanStateFor ¶ added in v0.4.0
func PlanStateFor(f PlanFacts) PlanStateResult
PlanStateFor follows the ordered precedence of the version-1 state table. This slice grants paid access only to personal Pro; ended states remain mappable even when a provider reports a now-unsupported tier.
type ProLimitsResolver ¶ added in v0.5.0
type ProLimitsResolver interface {
ResolveProLimits(string, PlanEffectGrants) (ProLimitsSnapshot, error)
}
type ProLimitsSnapshot ¶ added in v0.5.0
type ProLimitsSnapshot struct {
Version string
ProjectGuestsKnown bool
Limits models4datatug.PlanLimits
}
type PurchaseReadiness ¶ added in v0.5.0
type PurchaseReadiness struct {
DB dal.DB
Owner PlanEffectOwnerPort
Personal PersonalPlanOwnerPort
Config PlanConfigReader
Clock PlanClock
}
PurchaseReadiness verifies the current owner, the last actual Pro plan application, and its effective public plan in one read-only transaction.
func (PurchaseReadiness) ReadyForPurchase ¶ added in v0.5.0
func (r PurchaseReadiness) ReadyForPurchase(ctx context.Context, req PurchaseReadinessRequest) (bool, error)
type PurchaseReadinessRequest ¶ added in v0.5.0
type PurchaseReadinessRequest struct {
BuyerID, Mode, SiteID, Family, AccountID string
SubscriptionID, QuoteKey, SessionID, PlanID string
}
PurchaseReadinessRequest contains only server-verified session and quote identity. The host translates the authenticated payment status request.
type RegisterGithubProjectRequest ¶ added in v0.2.0
type RegisterGithubProjectRequest struct {
Org string `json:"org"`
Repo string `json:"repo"`
Folder string `json:"folder"`
Title string `json:"title"`
}
RegisterGithubProjectRequest describes a project that already exists in a GitHub repository.
func (RegisterGithubProjectRequest) Validate ¶ added in v0.2.0
func (v RegisterGithubProjectRequest) Validate() error
Validate validates the request.
type ServiceRefundProof ¶ added in v0.5.0
type ServiceRefundProof struct {
Known bool
HasPaidServiceInvoice bool
InvoiceID string
ServiceStartUTC time.Time
ServiceEndUTC time.Time
RefundedInFull bool
}
ServiceRefundProof describes the current owner's service plan, even when a historical subscription caused this revision. It is never inferred from the account-wide A+C cash snapshot. Unknown and absence are distinct.
type UsageReader ¶ added in v0.4.0
type UsageReader interface {
ReadUsage(context.Context, string, string) (*models4datatug.AIUsageRecord, error)
}
UsageReader reads the requested UTC month; nil means no count document.