facade4datatug

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 27 Imported by: 0

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.

Copyright 2026 Sneat.co

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrGitHubProjectConflict  = errors.New("GitHub project create conflict")
	ErrGitHubOutcomeUncertain = errors.New("GitHub project create outcome uncertain")
	ErrGitHubProjectInvalid   = errors.New("invalid GitHub project create command")
)
View Source
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")
)
View Source
var (
	ErrPersonalAccountUnavailable = errors.New("personal account unavailable")
	ErrForeignAccount             = errors.New("account is not the caller's personal account")
	ErrPlanUnavailable            = errors.New("plan response unavailable")
)
View Source
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")
)
View Source
var (
	ErrSharedProjectUnavailable  = errors.New("shared project creation is unavailable")
	ErrSharedProjectUnauthorized = errors.New("shared project creation is unauthorized")
	ErrSharedProjectConflict     = errors.New("shared project create command conflicts")
	ErrSharedProjectInvalid      = errors.New("invalid shared project create command")
)
View Source
var ErrGitHubProjectNotRegistered = errors.New("GitHub project is not registered")
View Source
var ErrGitHubQueryConflict = errors.New("GitHub query mutation conflict")
View Source
var ErrGitHubQueryInvalid = errors.New("invalid GitHub query mutation")
View Source
var ErrGitHubQueryOutcomeUncertain = errors.New("GitHub query mutation outcome uncertain")
View Source
var ErrPlanEffectUnproved = errors.New("plan effect is not proved")
View Source
var ErrProjectAIEligibilityUnavailable = errors.New("project AI eligibility unavailable")
View Source
var ErrProjectContactLimit = errors.New("protected project contact limit unavailable or exhausted")
View Source
var ErrProtectedProjectInventory = errors.New("protected project inventory could not be proved complete")
View Source
var ErrProtectedProjectQuota = errors.New("protected project quota unavailable or exhausted")
View Source
var ErrSharedProjectActivationUnavailable = errors.New("shared project activation is unavailable")

Functions

func InitializeProtectedProjectQuota added in v0.11.0

func InitializeProtectedProjectQuota(ctx context.Context, db dal.DB, options PaidSharedProjectOptions, actor, payer string, basis InitialProtectedProjectBasis, authority ProtectedProjectBasisAuthority) error

InitializeProtectedProjectQuota is one-time and transaction fenced. A host must bind an actual empty/import proof source before calling it; a caller or operator claim alone is insufficient. All creates refuse absent quota, so concurrent initialization cannot race an uncounted admission. Deletion and quota release require a future atomic allocation-retirement command; this count is not reset on payment renewal or subscription replacement.

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

type AdmissionReader added in v0.4.0

type AdmissionReader interface {
	ReadAdmission(context.Context, string, time.Time) (AdmissionState, error)
}

type AdmissionState added in v0.4.0

type AdmissionState struct {
	TodayUsed int64
	Blocked   string
}

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 CurrentProjectContactPort added in v0.12.0

type CurrentProjectContactPort interface {
	ReadCurrentProjectContact(context.Context, dal.ReadTransaction, contract4linkage.RelationshipEntityRef) (ProjectContactState, error)
}

type DALProtectedProjectInventory added in v0.15.0

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

DALProtectedProjectInventory uses collection-group scans but accepts records only under the exact spaces/{id}/ext/datatug/projects and spaces/{id}/ext/datatug/projectAdmissions ancestry. Group scans also find orphan subcollections whose parent Space document was deleted. The scan is intentionally unbounded by Firestore query limits; a hard local ceiling fails closed rather than returning a truncated count.

func NewDALProtectedProjectInventory added in v0.15.0

func NewDALProtectedProjectInventory(query dal.QueryExecutor) (*DALProtectedProjectInventory, error)

func (*DALProtectedProjectInventory) CompleteProtectedProjectBasis added in v0.15.0

func (i *DALProtectedProjectInventory) CompleteProtectedProjectBasis(ctx context.Context, mode, product, payer string) (InitialProtectedProjectBasis, 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 GitHubCreateRepository added in v0.14.0

type GitHubCreateRepository interface {
	Scope() GitHubCreateRepositoryScope
	CurrentHead(context.Context, string) (string, error)
	EnsureFolderEmpty(context.Context, string, string) error
	CreateFilesCommit(context.Context, string, string, string, map[string][]byte) (string, error)
	FindCommitByMarker(context.Context, string, string, string, map[string][]byte) (string, error)
}

GitHubCreateRepository is implemented by a per-request, actor-bound adapter around githubauth4datatug.AuthorizedGitHubRepository. Its methods never expose OAuth or installation tokens to this module or to a caller.

type GitHubCreateRepositoryScope added in v0.14.0

type GitHubCreateRepositoryScope struct {
	ActorID, Owner, Name, Permission string
	RepositoryID                     int64
}

type GitHubProjectAccess added in v0.14.0

type GitHubProjectAccess struct {
	SpaceID         string
	SharedProjectID string
	Binding         models4datatug.GitHubProjectBinding
}

type GitHubProjectCreateCommand added in v0.14.0

type GitHubProjectCreateCommand struct {
	ActorID, SpaceID, OperationID, Title string
	Source                               models4datatug.GitHubCreateSource
}

func (GitHubProjectCreateCommand) Validate added in v0.14.0

func (c GitHubProjectCreateCommand) Validate() error

type GitHubProjectCreateResult added in v0.14.0

type GitHubProjectCreateResult struct {
	ID              string `json:"id"`
	Storage         string `json:"storage"`
	Project         string `json:"project"`
	SpaceID         string `json:"spaceID"`
	SharedProjectID string `json:"sharedProjectID"`
	Branch          string `json:"branch"`
	BranchHead      string `json:"branchHead"`
	Revision        string `json:"revision"`
	TemplateID      string `json:"templateID"`
	TemplateCommit  string `json:"templateCommit"`
}

type GitHubQueryExpectedFile added in v0.14.0

type GitHubQueryExpectedFile struct {
	OID  string
	Mode string
	Size int64
}

type GitHubQueryFileChange added in v0.14.0

type GitHubQueryFileChange struct {
	Path    string
	Content []byte
	Delete  bool
}

type GitHubQueryRepository added in v0.14.0

type GitHubQueryRepository interface {
	Scope() GitHubCreateRepositoryScope
	PrepareQuerySave(context.Context, string, string, string, dto.SaveQueryRequest) (*GitHubQuerySavePlan, error)
	CurrentHead(context.Context, string) (string, error)
	CreateQueryCommit(context.Context, string, string, string, *GitHubQuerySavePlan) (string, error)
	FindQueryCommit(context.Context, string, string, string, *GitHubQuerySavePlan) (string, error)
}

type GitHubQuerySavePlan added in v0.14.0

type GitHubQuerySavePlan struct {
	Changes      []GitHubQueryFileChange
	ExpectedTree map[string]GitHubQueryExpectedFile
	Response     dto.SaveQueryResponse
}

type IDGenerator

type IDGenerator interface {
	// NewID returns the id of a new record.
	NewID(ctx context.Context) (string, error)
}

IDGenerator is a PORT: extension implementation packages stay outside this module. Published contracts and their DTO aliases may be reused; behavior 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 InitialProtectedProjectBasis added in v0.11.0

type InitialProtectedProjectBasis struct {
	Digest    string
	Allocated int64
}

InitialProtectedProjectBasis must be issued by a trusted complete-inventory verifier. It includes existing allocations across ALL Spaces for this payer. It must also independently bind actor to the verified context and may only read. No runtime reset or missing-record zero inference is provided. An imported count requires the verifier to prove matching immutable allocation records.

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 PaidProjectLinkageOptions added in v0.12.0

type PaidProjectLinkageOptions struct {
	Paid     PaidSharedProjectOptions
	Roles    ProjectRoleCatalog
	Contacts CurrentProjectContactPort
	Manager  ProjectRoleManagerPort
	Targets  ProjectContactRoleTargetPort
	Now      func() time.Time
}

type PaidProjectLinkagePolicy added in v0.12.0

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

PaidProjectLinkagePolicy is the DataTug implementation of Core's generic transaction policy. Host activation MUST declare datatug/projects protected before binding generic routes or creating records, then bind this policy for BOTH linkage directions. A UI role list never supplies authority.

func NewPaidProjectLinkagePolicy added in v0.12.0

func NewPaidProjectLinkagePolicy(o PaidProjectLinkageOptions) (*PaidProjectLinkagePolicy, error)

func (*PaidProjectLinkagePolicy) AuthorizeRelationshipMutation added in v0.12.0

type PaidProjectOwnerLinksOptions added in v0.12.0

type PaidProjectOwnerLinksOptions struct {
	Roles    ProjectRoleCatalog
	Owner    ProjectOwnerContactPort
	Contacts CurrentProjectContactPort
}

type PaidSharedProjectOptions added in v0.11.0

type PaidSharedProjectOptions struct {
	Version, Mode, Product string
	ContactLinks           *PaidProjectOwnerLinksOptions
	Config                 PlanConfig
	Directory              PersonalAccountDirectory
	Personal               PersonalPlanOwnerPort
	Owner                  interface {
		ReadOwner(context.Context, dal.ReadTransaction, string, string, string) (PlanOwnerFence, error)
	}
}

PaidSharedProjectOptions are reviewed server configuration, never request fields. This slice supports current personal Pro only. Business grant/AI policy is not inferred from missing limits or historical tier fixtures. Product mutation is LIVE-only: TEST checkout projections never create real shared projects. Future TEST product isolation needs a separate ref namespace.

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 PersonalPlanOwnerPort interface {
	VerifyPersonalOwner(context.Context, dal.ReadTransaction, string, string) error
}

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 PlanAccount struct {
	AccountID string `json:"accountId"`
	Kind      string `json:"kind"`
	Title     string `json:"title"`
	Plan      string `json:"plan"`
	Role      string `json:"role"`
	Pays      bool   `json:"pays"`
}

type PlanApplyOutcome added in v0.5.0

type PlanApplyOutcome string
const (
	PlanApplied    PlanApplyOutcome = "applied"
	PlanIdempotent PlanApplyOutcome = "idempotent"
	PlanObsolete   PlanApplyOutcome = "obsolete"
)

type PlanClock added in v0.4.0

type PlanClock interface{ Now() time.Time }

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
	// Zero grace stops paid access exactly at PaidUntil. Positive values are
	// explicit legacy policy; do not configure them for strict paid-through plans.
	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

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 PlanModel added in v0.4.0

type PlanModel struct {
	ID      string `json:"id"`
	Class   string `json:"class"`
	Weight  int64  `json:"weight"`
	Default bool   `json:"default"`
}

type PlanMoneyFence added in v0.5.0

type PlanMoneyFence struct {
	IngestEpoch, ReconciledEpoch int64
	Unresolved                   bool
}

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 PlanPaymentLine struct {
	ID, ProductFamily           string
	StartUTC, EndUTC            time.Time
	CashCents, RetainedTaxCents int64
	RetainedTaxKnown            bool
}

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 PlanRefund struct {
	ID               string
	GrossCents       int64
	LineGrossCents   map[string]int64
	AttributionKnown bool
}

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 PlanToday added in v0.4.0

type PlanToday struct {
	Used  int64 `json:"used"`
	Limit int64 `json:"limit"`
}

type PreparedSharedProjectCreate added in v0.10.0

type PreparedSharedProjectCreate struct {
	Binding   SharedProjectCreateBinding
	IssuedAt  time.Time
	Validator SharedProjectCreateTransactionAuthority
}

PreparedSharedProjectCreate is server-to-server only. Its validator privately owns the opaque Core reservation; that reservation never enters this DTO or a public response. The domain checks Binding and captures its validation clock AFTER preparation, before entering any retryable callback.

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 ProjectAIEligibility added in v0.16.0

type ProjectAIEligibility struct {
	AIAllowed bool   `json:"aiAllowed"`
	Reason    string `json:"reason,omitempty"`
}

ProjectAIEligibility is a minimal, server-computed projection. Actor membership and sponsor entitlement are proved separately before it is returned; no payer or subscription identifiers leave this package.

type ProjectContactRoleChange added in v0.12.0

type ProjectContactRoleChange struct {
	Contact          ProjectContactState
	Before, Proposed []string
}

type ProjectContactRoleTargetPort added in v0.12.0

type ProjectContactRoleTargetPort interface {
	AuthorizeProjectContactRoleChange(context.Context, dal.ReadTransaction, ProjectRoleMutationAuthorization, ProjectContactRoleChange) error
}

Target authority decides eligibility of adds/removals, including deliberate stale-contact cleanup; counting a stale link does not approve assigning one.

type ProjectContactState added in v0.12.0

type ProjectContactState struct {
	Ref            contract4linkage.RelationshipEntityRef
	Exists, Active bool
	UserID         string
}

ProjectContactState comes from the current full contact record in the supplied transaction, never a cached active-contact brief. Missing/inactive contacts still count while linked. UserID is used for authentication only. Being a Space member is not a requirement for an assigned project contact.

type ProjectOwnerContactPort added in v0.12.0

type ProjectOwnerContactPort interface {
	ResolveProjectOwnerContact(context.Context, dal.ReadTransaction, SharedProjectCreateBinding) (contract4linkage.RelationshipEntityRef, error)
}

This port resolves an EXISTING contact in the original create transaction. It must independently bind the actor to the verified context, without writes, nested transactions, new contacts or automatic Space membership. The domain rechecks current status/UID and constructs only reciprocal linkage writes.

type ProjectRoleCatalog added in v0.12.0

type ProjectRoleCatalog struct {
	Version   string
	Roles     []string
	OwnerRole string
}

ProjectRoleCatalog is server configuration. This list approves role IDs only; it grants no operations or authority. The host's current role/permission ports separately authorize the operation. No public request may supply the list.

type ProjectRoleEvidence added in v0.12.0

type ProjectRoleEvidence struct {
	Contact ProjectContactState
	Roles   []string
}

type ProjectRoleManagerPort added in v0.12.0

type ProjectRoleManagerPort interface {
	AuthorizeProjectRoleMutation(context.Context, dal.ReadTransaction, ProjectRoleMutationAuthorization) error
}

Manager authority must independently bind ActorID to the authenticated context and authorize with CURRENT project roles and platform guards. Space role alone does not supply a project role. Multiple contacts for one UID are separate evidence: the port must not silently union their privileges.

type ProjectRoleMutationAuthorization added in v0.12.0

type ProjectRoleMutationAuthorization struct {
	ActorID       string
	Project       models4datatug.SharedProjectRef
	ActorContacts []ProjectRoleEvidence
	Changes       []ProjectContactRoleChange
}

type ProtectedProjectBasisAuthority added in v0.11.0

type ProtectedProjectBasisAuthority interface {
	VerifyInitialProtectedProjectBasisInTransaction(context.Context, dal.ReadwriteTransaction, string, string, string, string, InitialProtectedProjectBasis) error
}

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 SharedProjectActivationOptions added in v0.15.0

type SharedProjectActivationOptions struct {
	Activator      contract4spaceus.TransactionalRoleCapabilityActivator
	RequiredRoles  []string
	InventoryQuery dal.QueryExecutor
}

SharedProjectActivationOptions are trusted host composition. The Core activator never runs for passive reads or precommitted reservations.

type SharedProjectCreateAuthority added in v0.10.0

type SharedProjectCreateAuthority interface {
	PrepareSharedProjectCreate(context.Context, SharedProjectCreateBinding) (PreparedSharedProjectCreate, error)
}

SharedProjectCreateAuthority is supplied by the host using released Core Space contracts: existing DataTug capability, current ordinary active Space, and server-configured content-management roles. It must not enable a module. Core reservation labels have a narrower grammar than client command IDs: the adapter must derive a server-owned lowercase command digest (<=64 chars) and purpose/stage labels, not pass arbitrary client CommandID through Core.

type SharedProjectCreateBinding added in v0.10.0

type SharedProjectCreateBinding struct {
	ActorID, SpaceID, CommandID, RequestDigest string
	// Paid binding is server-resolved. Legacy ownership-only commands leave it empty.
	PayerID, Mode, Product string
}

SharedProjectCreateBinding contains only immutable values. ActorID must come from the verified request context, never an HTTP body. A trusted adapter must independently bind it to that context when preparing Space authority.

type SharedProjectCreateCommand added in v0.10.0

type SharedProjectCreateCommand struct {
	ActorID, SpaceID, CommandID, Title string
}

func (SharedProjectCreateCommand) Validate added in v0.10.0

func (c SharedProjectCreateCommand) Validate() error

type SharedProjectCreateTransactionAuthority added in v0.10.0

type SharedProjectCreateTransactionAuthority interface {
	// ValidateSharedProjectCreateInTransaction must re-read current Space,
	// membership/role, enabled module and durable reservation evidence in this
	// exact transaction on EVERY invocation, including command replay. It may
	// only read: no nested transaction, writes, provider call or clock read.
	ValidateSharedProjectCreateInTransaction(context.Context, dal.ReadwriteTransaction, SharedProjectCreateBinding, time.Time) error
}

type SharedProjectService added in v0.10.0

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

SharedProjectService is deliberately separate from the private-project Facade, so existing callers do not acquire shared creation implicitly.

func NewActivatingPaidSharedProjectService added in v0.15.0

func NewActivatingPaidSharedProjectService(
	db dal.DB,
	ids IDGenerator,
	now func() time.Time,
	paid PaidSharedProjectOptions,
	activation SharedProjectActivationOptions,
) (*SharedProjectService, error)

NewActivatingPaidSharedProjectService is the explicit-create composition. It has no preflight SharedProjectCreateAuthority because a new Space may not yet have the DataTug capability. Its Create methods seed a complete paid quota basis before mutation, then plan/apply capability activation in the same transaction as project admission.

func NewPaidSharedProjectService added in v0.11.0

func NewPaidSharedProjectService(db dal.DB, ids IDGenerator, authority SharedProjectCreateAuthority, now func() time.Time, options PaidSharedProjectOptions) (*SharedProjectService, error)

NewPaidSharedProjectService connects admission to Create's own transaction. Activation still requires proved quota initialization/import, private rules, project contact-role guards and project-scoped hosted-write/AI enforcement. The legacy constructor remains ownership-only and must not activate paid routes.

func NewSharedProjectService added in v0.10.0

func NewSharedProjectService(db dal.DB, ids IDGenerator, authority SharedProjectCreateAuthority, now func() time.Time) (*SharedProjectService, error)

func (*SharedProjectService) AuthorizeGitHubProjectWrite added in v0.14.0

func (s *SharedProjectService) AuthorizeGitHubProjectWrite(ctx context.Context, actorID string, repositoryID int64, owner, name, folder string) (GitHubProjectAccess, error)

AuthorizeGitHubProjectWrite adds a current LIVE Pro grant to registered linked-contact membership. GitHub itself independently decides whether the current actor can write; Space roles are not a second GitHub edit ACL.

func (*SharedProjectService) Create added in v0.10.0

func (*SharedProjectService) CreateGitHubProject added in v0.14.0

CreateGitHubProject reserves paid shared-project capacity and owner linkage before provider mutation, then commits the exact pinned files with a branch head precondition. A failed/unknown provider result leaves the hidden intent and quota reserved for safe same-operation recovery; it never creates a second commit or silently frees capacity.

func (*SharedProjectService) EnsureProtectedProjectQuotaForCreate added in v0.15.0

func (s *SharedProjectService) EnsureProtectedProjectQuotaForCreate(ctx facade.ContextWithUser, binding SharedProjectCreateBinding) error

EnsureProtectedProjectQuotaForCreate is a command-bound explicit-submit preflight. It requires current paid, owner-contact and Core Space authority before scanning or seeding a missing quota. All protected allocation writers require an existing quota in their own transaction, so absence fences target-payer writes while the complete scan runs. The seed transaction repeats the command authority checks and continued quota absence before inserting the basis.

func (*SharedProjectService) PlanExplicitProjectCreateActivationInTransaction added in v0.15.0

func (s *SharedProjectService) PlanExplicitProjectCreateActivationInTransaction(
	ctx facade.ContextWithUser,
	tx dal.ReadwriteTransaction,
	binding SharedProjectCreateBinding,
	observedAt time.Time,
) (contract4spaceus.PreparedRoleCapabilityActivation, error)

PlanExplicitProjectCreateActivationInTransaction binds Core's activation plan to the verified caller and immutable paid create command. The caller must run all of its authorization, quota, receipt, repository, and owner contact checks before calling Apply on the returned value in this same DAL transaction, immediately before its first write.

func (*SharedProjectService) ReadGitHubProjectAIEligibility added in v0.16.0

func (s *SharedProjectService) ReadGitHubProjectAIEligibility(ctx context.Context, actorID string, repositoryID int64, owner, name, folder string) (ProjectAIEligibility, error)

ReadGitHubProjectAIEligibility binds the entitlement read to the registered immutable GitHub locator. The HTTP layer separately obtains fresh GitHub read permission for the exact repository before calling this method.

func (*SharedProjectService) ReadSharedProjectAIEligibility added in v0.16.0

func (s *SharedProjectService) ReadSharedProjectAIEligibility(ctx context.Context, actorID, spaceID, projectID string) (ProjectAIEligibility, error)

ReadSharedProjectAIEligibility authorizes the current linked project reader and then evaluates the payer recorded by that project's immutable admission. The client supplies a project locator only; it cannot select the payer.

func (*SharedProjectService) ResolveGitHubProject added in v0.14.0

func (s *SharedProjectService) ResolveGitHubProject(ctx context.Context, actorID string, repositoryID int64, owner, name, folder string) (GitHubProjectAccess, error)

ResolveGitHubProject verifies a ready immutable locator, paid admission provenance and a CURRENT active linked contact for this Firebase UID. It deliberately does not require an active paid term: reads survive a Pro plan ending. The caller also needs fresh GitHub user+App read authority for the exact immutable repository; this Space proof never replaces that check.

func (*SharedProjectService) SaveGitHubQuery added in v0.14.0

func (s *SharedProjectService) SaveGitHubQuery(ctx context.Context, actorID string, repositoryID int64, owner, name, folder string, request dto.SaveQueryRequest, repo GitHubQueryRepository) (*dto.SaveQueryResponse, error)

SaveGitHubQuery is the paid, actor-bound Cloud command. The provider commit is one CAS operation containing the metadata/body pair. A durable intent precedes that commit; retries prove the original commit before finalizing.

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.

Jump to

Keyboard shortcuts

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