mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-17 14:09:40 +02:00
Closes the gap between "invite flow UI exists" and "two users in the
same space actually see each other's data". Three pieces land together
because they're meaningless without each other.
mana-auth — new internal endpoint:
GET /api/v1/internal/users/:userId/memberships
Returns [{organizationId, role}, ...] for the user. mana-sync uses
this to populate the multi-member RLS session config.
mana-sync — membership lookup:
new internal/memberships package with an HTTP client + 5 min
per-user cache, fail-open (empty list = pre-Spaces behavior).
Config gets MANA_AUTH_URL (default http://localhost:3001).
Handler.NewHandler takes the Lookup. Every Push/Pull/Stream call
now passes spaceIDsFor(userID) to Store methods.
GetChangesSince + GetAllChangesSince extend their WHERE clause:
WHERE (user_id = $1 OR space_id = ANY($memberSpaces))
so co-members see each other's rows, not just the author.
apps/web — encryption skip for shared-space records:
encryptRecord now checks record.spaceId:
- `_personal:<userId>` sentinel OR no active shared space → encrypt
with user master key (E2E as today).
- Active space resolves to non-personal type AND spaceId matches
that space → skip encryption; write lands plaintext.
decryptRecord is unchanged because its per-field isEncrypted() guard
already passes plaintext through.
Phase-1 compromise: shared-space data is protected by server RLS
only, not E2E. Phase 2 adds per-Space shared keys with per-member
wrap — tracked in docs/plans/spaces-foundation.md.
Plus docs/plans/shared-space-smoketest.md: step-by-step Zwei-User-Test
mit erwarteten Ergebnissen und Debugging-Hinweisen bei Problemen.
Build + go test + web check all green.
Plan: docs/plans/spaces-foundation.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 lines
1.2 KiB
Go
39 lines
1.2 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
)
|
|
|
|
// Config holds all configuration for the sync server.
|
|
type Config struct {
|
|
Port int
|
|
DatabaseURL string
|
|
JWKSUrl string // mana-auth JWKS endpoint for JWT validation
|
|
ManaAuthURL string // mana-auth base URL for internal APIs (Space memberships)
|
|
CORSOrigins string
|
|
ManaCreditsURL string // mana-credits service URL for billing checks
|
|
ServiceKey string // Service-to-service auth key
|
|
}
|
|
|
|
// Load reads configuration from environment variables with sensible defaults.
|
|
func Load() *Config {
|
|
port, _ := strconv.Atoi(getEnv("PORT", "3050"))
|
|
|
|
return &Config{
|
|
Port: port,
|
|
DatabaseURL: getEnv("DATABASE_URL", "postgresql://mana:devpassword@localhost:5432/mana_sync"),
|
|
JWKSUrl: getEnv("JWKS_URL", "http://localhost:3001/api/auth/jwks"),
|
|
ManaAuthURL: getEnv("MANA_AUTH_URL", "http://localhost:3001"),
|
|
CORSOrigins: getEnv("CORS_ORIGINS", "http://localhost:5173,http://localhost:5188"),
|
|
ManaCreditsURL: getEnv("MANA_CREDITS_URL", "http://localhost:3061"),
|
|
ServiceKey: getEnv("MANA_SERVICE_KEY", "dev-service-key"),
|
|
}
|
|
}
|
|
|
|
func getEnv(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|