package artifacts import ( "bytes" "context" "errors" "fmt" "os" "strings" "gitea.maximumdirect.net/eric/narratio/internal/adapters/storage" "gitea.maximumdirect.net/eric/narratio/internal/manifest" ) const ( // MaxLegacyCurrentRunPointerBytes bounds the compatibility run selector. MaxLegacyCurrentRunPointerBytes int64 = 4 << 10 // MaxLegacyCurrentManifestBytes bounds the compatibility session manifest. MaxLegacyCurrentManifestBytes int64 = MaxRemoteSessionManifestBytes ) // This file is temporary compatibility support for sessions published before // immutable current commits. It can be removed after legacy remote state is migrated. func loadLegacyCurrentState( ctx context.Context, store storage.ObjectStore, sessionPrefix string, validation CurrentStateValidation, ) (*CurrentState, error) { currentManifestKey, currentRunIDKey := ResolveCurrentStateKeys(sessionPrefix) runID, err := loadLegacyCurrentRunPointer(ctx, store, currentRunIDKey) if err != nil { return nil, err } m, err := loadLegacyCurrentManifest(ctx, store, currentManifestKey) if err != nil { return nil, err } state := &CurrentState{ SessionPrefix: sessionPrefix, CurrentRunIDKey: currentRunIDKey, CurrentManifestKey: currentManifestKey, RunID: runID, Manifest: m, } if err := ValidateCurrentStateIdentity(state, validation); err != nil { return nil, err } return state, nil } func loadLegacyCurrentRunPointer(ctx context.Context, store storage.ObjectStore, currentRunIDKey string) (string, error) { key := strings.TrimSpace(currentRunIDKey) if key == "" { return "", fmt.Errorf("current run pointer key is required") } _, data, err := readCurrentStateControlObject(ctx, store, key, "legacy current run pointer", MaxLegacyCurrentRunPointerBytes) if err != nil { if errors.Is(err, os.ErrNotExist) { return "", &CurrentRunPointerMissingError{Key: key} } return "", err } runID := strings.TrimSpace(string(data)) if runID == "" { return "", fmt.Errorf("current run pointer %q is empty", key) } if err := ValidateRunIdentity(runID); err != nil { return "", fmt.Errorf("current run pointer %q contains an unsafe legacy run id; migrate remote state before use: %w", key, err) } return runID, nil } func loadLegacyCurrentManifest(ctx context.Context, store storage.ObjectStore, currentManifestKey string) (*manifest.Manifest, error) { key := strings.TrimSpace(currentManifestKey) if key == "" { return nil, fmt.Errorf("current manifest key is required") } _, data, err := readCurrentStateControlObject(ctx, store, key, "legacy current manifest", MaxLegacyCurrentManifestBytes) if err != nil { if errors.Is(err, os.ErrNotExist) { return nil, &CurrentManifestMissingError{Key: key} } return nil, err } m, err := (&manifest.LocalStore{}).LoadReader(ctx, bytes.NewReader(data)) if err != nil { return nil, fmt.Errorf("current manifest decode failed: %w", err) } return m, nil }