{"id":34133844,"url":"https://github.com/codespace-operator/common","last_synced_at":"2026-03-11T11:02:58.329Z","repository":{"id":313023631,"uuid":"1049128596","full_name":"codespace-operator/common","owner":"codespace-operator","description":"Shared utilities across projects","archived":false,"fork":false,"pushed_at":"2025-09-07T00:28:25.000Z","size":163,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-17T12:23:52.868Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codespace-operator.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-02T14:24:34.000Z","updated_at":"2025-09-07T00:28:27.000Z","dependencies_parsed_at":"2025-09-03T13:30:57.096Z","dependency_job_id":"3db55b30-62c7-4c73-89c7-6ede08b3618f","html_url":"https://github.com/codespace-operator/common","commit_stats":null,"previous_names":["codespace-operator/common"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/codespace-operator/common","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codespace-operator%2Fcommon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codespace-operator%2Fcommon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codespace-operator%2Fcommon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codespace-operator%2Fcommon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codespace-operator","download_url":"https://codeload.github.com/codespace-operator/common/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codespace-operator%2Fcommon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30379264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T06:09:32.197Z","status":"ssl_error","status_checked_at":"2026-03-11T06:09:17.086Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-15T01:14:08.870Z","updated_at":"2026-03-11T11:02:58.318Z","avatar_url":"https://github.com/codespace-operator.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Codespace Common Modules\n\nThis repo contains reusable building blocks used within several applications.\n\n- `pkg/auth`: pluggable authentication (OIDC + local), cookie/session helpers, middleware\n- `pkg/rbac`: Casbin-backed authorization with hot-reload policies \u0026 HTTP helpers\n\n## Quick links\n\n- [pkg/auth/README.md](pkg/auth/README.md) – configure OIDC or local login, mint/validate sessions\n- [pkg/rbac/README.md](pkg/rbac/README.md) – load model/policy, enforce permissions, middleware\n\n## Minimal example (auth + rbac together)\n\n```go\npackage main\n\nimport (\n    \"context\"\n    \"log/slog\"\n    \"net/http\"\n    \"os\"\n    \"time\"\n\n    \"github.com/codespace-operator/common/auth/pkg/auth\"\n    \"github.com/codespace-operator/common/auth/pkg/rbac\"\n)\n\nfunc main() {\n    logger := slog.New(slog.NewTextHandler(os.Stdout, nil))\n\n    // --- Auth -----------------------------------------------------------------\n    am, err := auth.NewAuthManager(\u0026auth.AuthConfig{\n        JWTSecret:         os.Getenv(\"JWT_SECRET\"),           // required\n        SessionCookieName: \"codespace_session\",               // optional\n        SessionTTL:        8 * time.Hour,                     // optional\n        AllowTokenParam:   false,                             // discourage\n        OIDC: \u0026auth.OIDCConfig{\n            IssuerURL:    os.Getenv(\"OIDC_ISSUER\"),\n            ClientID:     os.Getenv(\"OIDC_CLIENT_ID\"),\n            ClientSecret: os.Getenv(\"OIDC_CLIENT_SECRET\"),\n            RedirectURL:  os.Getenv(\"OIDC_REDIRECT_URL\"),     // e.g. https://app.example.com/auth/sso/callback\n            Scopes:       []string{\"openid\",\"profile\",\"email\"},\n            // InsecureSkipVerify: true, // DEV ONLY\n        },\n        Local: \u0026auth.LocalConfig{\n            Enabled:               true,       // handy for dev/bootstrap\n            UsersPath:             \"\",         // optional YAML/JSON file (see pkg/auth/README)\n            BootstrapLoginAllowed: true,\n            BootstrapUser:         \"admin\",\n            BootstrapPasswd:       \"admin\",\n        },\n    }, logger)\n    if err != nil { panic(err) }\n\n    authmw := auth.NewMiddleware(am, logger)\n\n    // --- RBAC -----------------------------------------------------------------\n    r, err := rbac.NewRBAC(context.Background(), rbac.RBACConfig{\n        // Can also be provided via env RBAC_MODEL_PATH / RBAC_POLICY_PATH\n        ModelPath:  \"\", // defaults to /etc/codespace-operator/rbac/model.conf\n        PolicyPath: \"\", // defaults to /etc/codespace-operator/rbac/policy.csv\n        Logger:     logger,\n    })\n    if err != nil { panic(err) }\n    rbacmw := rbac.NewMiddleware(r, logger)\n\n    // --- HTTP wiring ----------------------------------------------------------\n    mux := http.NewServeMux()\n\n    // Auth endpoints (very thin examples)\n    mux.HandleFunc(\"/auth/oidc/start\", func(w http.ResponseWriter, r *http.Request) {\n        am.GetProvider(auth.OIDC_PROVIDER).StartAuth(w, r, \"/\")\n    })\n    mux.HandleFunc(\"/auth/sso/callback\", func(w http.ResponseWriter, r *http.Request) {\n        claims, err := am.GetProvider(auth.OIDC_PROVIDER).HandleCallback(w, r)\n        if err != nil { http.Error(w, err.Error(), 400); return }\n        // issue app session cookie\n        if _, err := am.IssueSession(w, r, claims); err != nil { http.Error(w, err.Error(), 500); return }\n        http.Redirect(w, r, \"/\", http.StatusFound)\n    })\n    mux.HandleFunc(\"/auth/local/login\", func(w http.ResponseWriter, r *http.Request) {\n        if r.Method != http.MethodPost { http.Error(w, \"POST only\", 405); return }\n        lp := am.GetLocalProvider()\n        if lp == nil { http.Error(w, \"local disabled\", 400); return }\n        user := r.FormValue(\"username\")\n        pass := r.FormValue(\"password\")\n        claims, err := lp.Authenticate(user, pass)\n        if err != nil { http.Error(w, \"invalid creds\", 401); return }\n        am.IssueSession(w, r, claims)\n        w.WriteHeader(204)\n    })\n    mux.HandleFunc(\"/auth/logout\", func(w http.ResponseWriter, r *http.Request) {\n        am.ClearAuthCookie(w)\n        // best effort provider logout\n        if p := am.GetProvider(auth.OIDC_PROVIDER); p != nil { _ = p.Logout(w, r) }\n    })\n\n    // Protected API: user must be authenticated AND authorized to create a session in \"team-a\"\n    mux.Handle(\"/api/sessions\", authmw.RequireAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        if _, ok := rbacmw.MustCan(w, r, \"session\", \"create\", \"team-a\"); !ok { return }\n        w.Write([]byte(`{\"ok\":true}`))\n    })))\n\n    // Optional auth for UI/static\n    root := authmw.OptionalAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n        w.Write([]byte(\"hello\"))\n    }))\n    mux.Handle(\"/\", root)\n\n    addr := \":8080\"\n    logger.Info(\"listening\", \"addr\", addr)\n    _ = http.ListenAndServe(addr, mux)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodespace-operator%2Fcommon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodespace-operator%2Fcommon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodespace-operator%2Fcommon/lists"}