Documentation
¶
Overview ¶
Package originbind owns one invariant: a workspace is bound to one origin.
Both surfaces that can change which origin owns a workspace live behind it — `gadak init` and PUT onboarding/connect/ — so the decision cannot exist on one path and not the other. That split is exactly how GDK-247 happened: the CLI path was closed and the unauthenticated HTTP path was not.
It is not part of internal/workspace, which mounts profiles under /w/ and imports internal/server: the server calls this, so that would cycle.
Index ¶
- Constants
- func CanonicalSite(raw string) string
- func ClearStandalone(next *config.Config)
- func DropStandaloneProjection(cfg *config.Config, db *store.DB) (store.OriginReset, error)
- func LocalData(cfg *config.Config) (n int, persist string, err error)
- func RefuseIfOpen(cfg *config.Config) error
- func RefuseReplace(cfg *config.Config, replace bool) error
- func RefuseSiteRebind(cfg *config.Config, newSite string) error
- type ReplaceRefusedError
- type SiteBoundError
- type WorkspaceOpenError
Constants ¶
const ErrCodeReplaceRefused = "standalone_data_present"
ErrCodeReplaceRefused is the --json / HTTP "error" value when a connected init or onboarding connect refuses to take over a standalone workspace that holds data. The string is a CLI --json contract; do not change it.
Variables ¶
This section is empty.
Functions ¶
func CanonicalSite ¶ added in v0.17.0
CanonicalSite is the compare key for site rebind: scheme + host, no path, no trailing slash. Scheme-less input is treated as https, matching internal/server.normalizeSite.
func ClearStandalone ¶
ClearStandalone is the single owner of "origin is now a Jira site, so this workspace is no longer standalone". Reached only after RefuseReplace (or an explicit replace opt-in). Empty standalone workspaces take this path too: once connected, Kind must be cleared.
func DropStandaloneProjection ¶ added in v0.16.1
DropStandaloneProjection is the conversion cleanup both CLI init and HTTP onboarding must run: drop the seeded LOC wiki scope, then hand both sources to the store's origin-replacement owner.
What that owner removes is decided by the table classification in internal/store/origin_scope.go, not here. It used to be a literal list of DELETEs, and four tables added by later migrations were never added to it — so a converted workspace kept plugin enrichments, feed read marks, field usage and sync runs that named the retired origin's keys, which do not go stale but rebind to whatever the new site put at the same key (GDK-418).
The returned OriginReset is what to tell the user; an empty String() means nothing personal was bound to the old origin.
func LocalData ¶
LocalData reports how much locally originated data this standalone workspace holds, and the origin persist path (via origin.PersistPath — never rebuilt from string pieces). The returned n is max(issues, pages).
Each of issues and pages is itself max(mirror, origin):
- mirror: SELECT COUNT(*) FROM issues / pages, only if gadak.db exists (store.Open would create it)
- origin issues: Search on the in-process origin, only if the persist file or a sibling legacy YAML already exists (origin.Client would create an empty persist)
- origin pages: wiki SearchPages, best-effort (a SearchPages miss is 0, not a LocalData failure — issuetap may not implement CQL)
init --standalone creates a persist file with a project fixture and no issues or pages, so that empty-origin case is n==0 and the common "I tried it, now I want to connect" path is not blocked.
func RefuseIfOpen ¶ added in v0.16.1
RefuseIfOpen stops a CLI standalone→connected conversion while another process has this workspace open. HTTP conversion runs inside the owner process and must not call this.
Two questions, because one answer does not cover both holders:
A live `gadak serve` is found through the home-root run directory (serveaddr) and an identity probe — not leftover serve-origin.json, which GDK-936 made meaningless. Gadak.app opens no port at all (its assets go through a custom scheme handler), so serveaddr cannot see it. The persist's open marker can (GDK-971). That marker is advisory and never arbitrates writes — WAL does that — it only says someone is holding this workspace.
func RefuseReplace ¶
RefuseReplace stops a connected init / onboarding connect from silently changing which origin owns a standalone workspace that holds locally originated data. An empty standalone workspace (tried it, nothing filed) is not a hazard and is allowed through.
JSON rendering stays at the CLI call site — this returns an error only.
func RefuseSiteRebind ¶ added in v0.17.0
RefuseSiteRebind stops a connected init / onboarding connect from silently re-pointing a workspace at a different site. Empty cfg.Site is first bind (or standalone/paired with no site) and is allowed. Same site after CanonicalSite is token rotation and is allowed.
Types ¶
type ReplaceRefusedError ¶
ReplaceRefusedError is returned when RefuseReplace blocks a connect. Error() is the human sentence previously printed by gadak init.
func (*ReplaceRefusedError) Error ¶
func (e *ReplaceRefusedError) Error() string
type SiteBoundError ¶ added in v0.17.0
type SiteBoundError struct {
Bound string
}
SiteBoundError is returned when a connected workspace is asked to bind a different site. Issue keys are not globally unique; changing origin means a new workspace (package comment). Error() is the CLI/HTTP sentence.
func (*SiteBoundError) Error ¶ added in v0.17.0
func (e *SiteBoundError) Error() string
type WorkspaceOpenError ¶ added in v0.16.1
WorkspaceOpenError is returned when CLI conversion would run while another process (serve or the desktop app) has this workspace open.
func (*WorkspaceOpenError) Error ¶ added in v0.16.1
func (e *WorkspaceOpenError) Error() string