{"versions":{"1.2.1":{"name":"@gitlab/opencode-gitlab-auth","version":"1.2.1","description":"GitLab OAuth authentication plugin for OpenCode","type":"module","main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git"},"bugs":{"url":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues"},"homepage":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth#readme","scripts":{"build":"tsc","clean":"rm -rf dist","rebuild":"npm run clean && npm run build","lint":"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","lint-staged":"lint-staged","prepare":"husky install","prepublishOnly":"npm run build","semantic-release":"semantic-release"},"keywords":["opencode","gitlab","oauth","authentication","plugin"],"author":{"name":"Vladimir Glafirov"},"license":"MIT","peerDependencies":{"@opencode-ai/plugin":"*"},"dependencies":{"fastify":"^5.2.0","@fastify/rate-limit":"^10.2.0","@opencode-ai/plugin":"^1.0.127","open":"^10.0.0"},"devDependencies":{"@commitlint/cli":"^18.4.3","@commitlint/config-conventional":"^18.4.3","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/gitlab":"^13.0.3","@semantic-release/npm":"^11.0.2","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.15.0","@typescript-eslint/parser":"^6.15.0","eslint":"^8.56.0","eslint-config-prettier":"^9.1.0","husky":"^8.0.3","lint-staged":"^15.2.0","prettier":"^3.1.1","semantic-release":"^22.0.12","typescript":"^5.0.0"},"engines":{"node":">=18.0.0","npm":">=9.0.0"},"gitHead":"764272772389b18a2a7d427b3a6a79bd09c5f54c","_id":"@gitlab/opencode-gitlab-auth@1.2.1","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-/3tnlu0k22MRwlUVkmT7SYOOckrk+hZkcXY6l43K6H4KwuIBs2Tkn2eWDF1ReNWaTXxjJG7OlQtRhGu6yXzIqQ==","shasum":"c132ada801e07a4f7368f4d9fdfa5e89f6357454","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@gitlab/opencode-gitlab-auth/-/opencode-gitlab-auth-1.2.1.tgz","fileCount":20,"unpackedSize":111570,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC2h03FIU2PYoM91969zfcim2A0GPPt94a5kQ4BP5xWhgIhAPcpOwB854Nju/bhxkaT6ak18iUQn20V2DaGpXiYKwhM"}],"size":48484},"_npmUser":{"name":"anonymous","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"gitlab","oidcConfigId":"oidc:f63c4784-e135-4ef3-a26e-f4c4b9cc652d"}},"directories":{},"maintainers":[{"name":"anonymous","email":"rhunt@gitlab.com"},{"name":"anonymous","email":"frontend-administration@gitlab.com"},{"name":"anonymous","email":"tzallmann@gitlab.com"},{"name":"anonymous","email":"incoming+gitlab-com/npm-bot@incoming.gitlab.com"},{"name":"anonymous","email":"apanchal@gitlab.com"},{"name":"anonymous","email":"jhope@gitlab.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/opencode-gitlab-auth_1.2.1_1767817729639_0.9260464009484464"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2026-01-07T20:28:49.789Z","publish_time":1767817729789,"_source_registry_name":"default","contributors":[]},"1.2.0":{"name":"@gitlab/opencode-gitlab-auth","version":"1.2.0","keywords":["opencode","gitlab","oauth","authentication","plugin"],"author":{"name":"Vladimir Glafirov"},"license":"MIT","_id":"@gitlab/opencode-gitlab-auth@1.2.0","maintainers":[{"name":"anonymous","email":"rhunt@gitlab.com"},{"name":"anonymous","email":"frontend-administration@gitlab.com"},{"name":"anonymous","email":"tzallmann@gitlab.com"},{"name":"anonymous","email":"incoming+gitlab-com/npm-bot@incoming.gitlab.com"},{"name":"anonymous","email":"apanchal@gitlab.com"},{"name":"anonymous","email":"jhope@gitlab.com"}],"homepage":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth#readme","bugs":{"url":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues"},"dist":{"shasum":"ab4c70c1c6a466328f94de3145d3d93094217deb","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@gitlab/opencode-gitlab-auth/-/opencode-gitlab-auth-1.2.0.tgz","fileCount":19,"integrity":"sha512-DxmrufucqbW9L+OFdH+4G2YDpMj9QK4ib7/OGH/44f4hHn5z3GXvu0UKvDqktJ4XHC6MnnAE3o8M7BEfaQhFmQ==","signatures":[{"sig":"MEUCIQDYRJM9Zrro9OtlGrL6NVKx3SVZ6l2K6S54PkoZ8M0LFwIgLbbmnl+Vmo1yQNU6pWNEndzwG9IeIkklrmqQVYcfXb4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87167,"size":23586},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"npm":">=9.0.0","node":">=18.0.0"},"gitHead":"43e3445e7f477132e7a1c830782d2d5ceb295b6a","scripts":{"lint":"eslint src --ext .ts","build":"tsc","clean":"rm -rf dist","format":"prettier --write \"src/**/*.ts\"","prepare":"husky install","rebuild":"npm run clean && npm run build","lint:fix":"eslint src --ext .ts --fix","lint-staged":"lint-staged","format:check":"prettier --check \"src/**/*.ts\"","prepublishOnly":"npm run build","semantic-release":"semantic-release"},"_npmUser":{"name":"anonymous","email":"frontend-administration@gitlab.com"},"repository":{"url":"git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git","type":"git"},"_npmVersion":"11.6.2","description":"GitLab OAuth authentication plugin for OpenCode","directories":{},"_nodeVersion":"25.2.1","dependencies":{"open":"^10.0.0","fastify":"^5.2.0","@fastify/rate-limit":"^10.2.0","@opencode-ai/plugin":"^1.0.127"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"husky":"^8.0.3","eslint":"^8.56.0","prettier":"^3.1.1","typescript":"^5.0.0","@types/node":"^20.0.0","lint-staged":"^15.2.0","@commitlint/cli":"^18.4.3","semantic-release":"^22.0.12","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^11.0.2","eslint-config-prettier":"^9.1.0","@semantic-release/gitlab":"^13.0.3","@typescript-eslint/parser":"^6.15.0","@semantic-release/changelog":"^6.0.3","@commitlint/config-conventional":"^18.4.3","@typescript-eslint/eslint-plugin":"^6.15.0"},"peerDependencies":{"@opencode-ai/plugin":"*"},"_npmOperationalInternal":{"tmp":"tmp/opencode-gitlab-auth_1.2.0_1767815925213_0.6744678151783827","host":"s3://npm-registry-packages-npm-production"},"_cnpmcore_publish_time":"2026-01-07T19:58:45.357Z","publish_time":1767815925357,"_source_registry_name":"default","contributors":[]},"1.3.0":{"name":"@gitlab/opencode-gitlab-auth","version":"1.3.0","description":"GitLab OAuth authentication plugin for OpenCode","type":"module","main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git"},"bugs":{"url":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues"},"homepage":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth#readme","scripts":{"build":"tsc","clean":"rm -rf dist","rebuild":"npm run clean && npm run build","lint":"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","lint-staged":"lint-staged","prepare":"husky install","prepublishOnly":"npm run build","semantic-release":"semantic-release"},"keywords":["opencode","opencode-plugin","gitlab","gitlab-duo","oauth","oauth2","authentication","auth","login","pkce","security","plugin","personal-access-token","pat","developer-tools","devops","ai","typescript"],"author":{"name":"Vladimir Glafirov","email":"vglafirov@gitlab.com","url":"https://gitlab.com/vglafirov"},"license":"MIT","peerDependencies":{"@opencode-ai/plugin":"*"},"dependencies":{"fastify":"^5.2.0","@fastify/rate-limit":"^10.2.0","@opencode-ai/plugin":"^1.0.127","open":"^10.0.0"},"devDependencies":{"@commitlint/cli":"^18.4.3","@commitlint/config-conventional":"^18.4.3","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/gitlab":"^13.0.3","@semantic-release/npm":"^11.0.2","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.15.0","@typescript-eslint/parser":"^6.15.0","eslint":"^8.56.0","eslint-config-prettier":"^9.1.0","husky":"^8.0.3","lint-staged":"^15.2.0","prettier":"^3.1.1","semantic-release":"^22.0.12","typescript":"^5.0.0"},"engines":{"node":">=18.0.0","npm":">=9.0.0"},"gitHead":"c1de805155641bb9594172ff9a9d5ea580b980f7","_id":"@gitlab/opencode-gitlab-auth@1.3.0","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-Jd0jXYip0FoKuPLIIHh5vIt3FtRbYLZm9um7nG/Nbv34YbLcaoFRnoiqoD5t/xKWc/lae+lj3f3c/lyKhjnIpQ==","shasum":"53f48bf3a09b3c7bb3c0944043b7902835dab7dd","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@gitlab/opencode-gitlab-auth/-/opencode-gitlab-auth-1.3.0.tgz","fileCount":20,"unpackedSize":111951,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFX7g7QNC+O8hM1Ou7nyMdQZzmZ9UEAcJGtHxK8zFuBXAiEA+96HQWSfBiNtaUM+hQA5n6DzJgNpPR4a4dKp0/OFSWM="}],"size":48618},"_npmUser":{"name":"anonymous","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"gitlab","oidcConfigId":"oidc:f63c4784-e135-4ef3-a26e-f4c4b9cc652d"}},"directories":{},"maintainers":[{"name":"anonymous","email":"rhunt@gitlab.com"},{"name":"anonymous","email":"frontend-administration@gitlab.com"},{"name":"anonymous","email":"tzallmann@gitlab.com"},{"name":"anonymous","email":"incoming+gitlab-com/npm-bot@incoming.gitlab.com"},{"name":"anonymous","email":"apanchal@gitlab.com"},{"name":"anonymous","email":"jhope@gitlab.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/opencode-gitlab-auth_1.3.0_1768296062945_0.6113822793980632"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2026-01-13T09:21:03.088Z","publish_time":1768296063088,"_source_registry_name":"default","contributors":[]},"1.3.1":{"name":"@gitlab/opencode-gitlab-auth","version":"1.3.1","description":"GitLab OAuth authentication plugin for OpenCode","type":"module","main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git"},"bugs":{"url":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues"},"homepage":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth#readme","scripts":{"build":"tsc","clean":"rm -rf dist","rebuild":"npm run clean && npm run build","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","lint-staged":"lint-staged","prepare":"husky install","prepublishOnly":"npm run build","semantic-release":"semantic-release"},"keywords":["opencode","opencode-plugin","gitlab","gitlab-duo","oauth","oauth2","authentication","auth","login","pkce","security","plugin","personal-access-token","pat","developer-tools","devops","ai","typescript"],"author":{"name":"Vladimir Glafirov","email":"vglafirov@gitlab.com","url":"https://gitlab.com/vglafirov"},"license":"MIT","peerDependencies":{"@opencode-ai/plugin":"*"},"dependencies":{"@fastify/rate-limit":"^10.2.0","@opencode-ai/plugin":"*","fastify":"^5.2.0","open":"^10.0.0"},"devDependencies":{"@commitlint/cli":"^18.4.3","@commitlint/config-conventional":"^18.4.3","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/gitlab":"^13.0.3","@semantic-release/npm":"^11.0.2","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.15.0","@typescript-eslint/parser":"^6.15.0","@vitest/coverage-v8":"^4.0.17","eslint":"^8.56.0","eslint-config-prettier":"^9.1.0","husky":"^8.0.3","lint-staged":"^15.2.0","prettier":"^3.1.1","semantic-release":"^22.0.12","typescript":"^5.0.0","vitest":"^4.0.17"},"engines":{"node":">=18.0.0","npm":">=9.0.0"},"gitHead":"2dcb4dac094e7af09bf0836efddfeff3bc1c2d58","_id":"@gitlab/opencode-gitlab-auth@1.3.1","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-BB0emSuqr5Eo0NJME9+nYGA2KuAw+LWdlJ55zlZ8XL2BBQE9dvhkPZxeb5/WLpSF3K9pYFYXsxAiANdRh90phw==","shasum":"17d6f90206c872386ab63e2057fc523a32845de2","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@gitlab/opencode-gitlab-auth/-/opencode-gitlab-auth-1.3.1.tgz","fileCount":20,"unpackedSize":115746,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDlFgAbJidB4DXKoxVZ32g+gZQEHgIR2m+vDsmEhpFMDAIhANW20XhzP7srAcVwLB757MxX627SuShEurxfaERk+MSb"}],"size":49590},"_npmUser":{"name":"anonymous","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"gitlab","oidcConfigId":"oidc:f63c4784-e135-4ef3-a26e-f4c4b9cc652d"}},"directories":{},"maintainers":[{"name":"anonymous","email":"rhunt@gitlab.com"},{"name":"anonymous","email":"frontend-administration@gitlab.com"},{"name":"anonymous","email":"tzallmann@gitlab.com"},{"name":"anonymous","email":"incoming+gitlab-com/npm-bot@incoming.gitlab.com"},{"name":"anonymous","email":"apanchal@gitlab.com"},{"name":"anonymous","email":"jhope@gitlab.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/opencode-gitlab-auth_1.3.1_1769013697468_0.3381668782873639"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2026-01-21T16:41:37.638Z","publish_time":1769013697638,"_source_registry_name":"default","contributors":[]},"1.3.2":{"name":"@gitlab/opencode-gitlab-auth","version":"1.3.2","description":"GitLab OAuth authentication plugin for OpenCode","type":"module","main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git"},"bugs":{"url":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues"},"homepage":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth#readme","scripts":{"build":"tsc","clean":"rm -rf dist","rebuild":"npm run clean && npm run build","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","lint-staged":"lint-staged","prepare":"husky install","prepublishOnly":"npm run build","semantic-release":"semantic-release"},"keywords":["opencode","opencode-plugin","gitlab","gitlab-duo","oauth","oauth2","authentication","auth","login","pkce","security","plugin","personal-access-token","pat","developer-tools","devops","ai","typescript"],"author":{"name":"Vladimir Glafirov","email":"vglafirov@gitlab.com","url":"https://gitlab.com/vglafirov"},"license":"MIT","peerDependencies":{"@opencode-ai/plugin":"*"},"dependencies":{"@fastify/rate-limit":"^10.2.0","@opencode-ai/plugin":"*","fastify":"^5.2.0","open":"^10.0.0"},"devDependencies":{"@commitlint/cli":"^18.4.3","@commitlint/config-conventional":"^18.4.3","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/gitlab":"^13.0.3","@semantic-release/npm":"^11.0.2","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.15.0","@typescript-eslint/parser":"^6.15.0","@vitest/coverage-v8":"^4.0.17","eslint":"^8.56.0","eslint-config-prettier":"^9.1.0","husky":"^8.0.3","lint-staged":"^15.2.0","prettier":"^3.1.1","semantic-release":"^22.0.12","typescript":"^5.0.0","vitest":"^4.0.17"},"engines":{"node":">=18.0.0","npm":">=9.0.0"},"gitHead":"5125a5bf3fbc7dfb6a84129a62fc4c12621beb43","_id":"@gitlab/opencode-gitlab-auth@1.3.2","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-pvGrC+aDVLY8bRCC/fZaG/Qihvt2r4by5xbTo5JTSz9O7yIcR6xG2d9Wkuu4bcXFz674z2C+i5bUk+J/RSdBpg==","shasum":"bb84782c5290ff54e0577fe45e8abc8158ec03d1","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@gitlab/opencode-gitlab-auth/-/opencode-gitlab-auth-1.3.2.tgz","fileCount":20,"unpackedSize":115745,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC21HKV6RI4adfILUWYQIQWW8M70Eh7efZzFUBRPDJJZgIhAIncCUqZ/nt8dypAQ92EpbuGIrpjeqke2/LaXSR/PT/I"}],"size":49593},"_npmUser":{"name":"anonymous","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"gitlab","oidcConfigId":"oidc:f63c4784-e135-4ef3-a26e-f4c4b9cc652d"}},"directories":{},"maintainers":[{"name":"anonymous","email":"rhunt@gitlab.com"},{"name":"anonymous","email":"frontend-administration@gitlab.com"},{"name":"anonymous","email":"tzallmann@gitlab.com"},{"name":"anonymous","email":"incoming+gitlab-com/npm-bot@incoming.gitlab.com"},{"name":"anonymous","email":"apanchal@gitlab.com"},{"name":"anonymous","email":"jhope@gitlab.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/opencode-gitlab-auth_1.3.2_1769013842519_0.28964482233323086"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2026-01-21T16:44:02.683Z","publish_time":1769013842683,"_source_registry_name":"default","contributors":[]},"1.3.3":{"name":"@gitlab/opencode-gitlab-auth","version":"1.3.3","description":"GitLab OAuth authentication plugin for OpenCode","type":"module","main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git"},"bugs":{"url":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues"},"homepage":"https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth#readme","scripts":{"build":"tsc","clean":"rm -rf dist","rebuild":"npm run clean && npm run build","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","lint-staged":"lint-staged","prepare":"husky install","prepublishOnly":"npm run build","semantic-release":"semantic-release"},"keywords":["opencode","opencode-plugin","gitlab","gitlab-duo","oauth","oauth2","authentication","auth","login","pkce","security","plugin","personal-access-token","pat","developer-tools","devops","ai","typescript"],"author":{"name":"Vladimir Glafirov","email":"vglafirov@gitlab.com","url":"https://gitlab.com/vglafirov"},"license":"MIT","peerDependencies":{"@opencode-ai/plugin":"*"},"dependencies":{"@fastify/rate-limit":"^10.2.0","@opencode-ai/plugin":"*","fastify":"^5.2.0","open":"^10.0.0"},"devDependencies":{"@commitlint/cli":"^18.4.3","@commitlint/config-conventional":"^18.4.3","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/gitlab":"^13.0.3","@semantic-release/npm":"^11.0.2","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.15.0","@typescript-eslint/parser":"^6.15.0","@vitest/coverage-v8":"^4.0.17","eslint":"^8.56.0","eslint-config-prettier":"^9.1.0","husky":"^8.0.3","lint-staged":"^15.2.0","prettier":"^3.1.1","semantic-release":"^22.0.12","typescript":"^5.0.0","vitest":"^4.0.17"},"engines":{"node":">=18.0.0","npm":">=9.0.0"},"gitHead":"23002b61f0e2cea848b9ef0e7e6ea152213d5af8","_id":"@gitlab/opencode-gitlab-auth@1.3.3","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-FT+KsCmAJjtqWr1YAq0MywGgL9kaLQ4apmsoowAXrPqHtoYf2i/nY10/A+L06kNj22EATeEDRpbB1NWXMto/SA==","shasum":"5fd30e3e63f84d01321566a89ac9962d9d09535e","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@gitlab/opencode-gitlab-auth/-/opencode-gitlab-auth-1.3.3.tgz","fileCount":20,"unpackedSize":116236,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDZxj4fydXtBlsK+MGcNnk1MNC7mKLcozOvNo0cfrqLdAIgFDmHWekhK/ek4cJ7TUaGZOQKX0Qad6mac/LEfQAhRd4="}],"size":49730},"_npmUser":{"name":"anonymous","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"gitlab","oidcConfigId":"oidc:f63c4784-e135-4ef3-a26e-f4c4b9cc652d"}},"directories":{},"maintainers":[{"name":"anonymous","email":"rhunt@gitlab.com"},{"name":"anonymous","email":"frontend-administration@gitlab.com"},{"name":"anonymous","email":"tzallmann@gitlab.com"},{"name":"anonymous","email":"incoming+gitlab-com/npm-bot@incoming.gitlab.com"},{"name":"anonymous","email":"apanchal@gitlab.com"},{"name":"anonymous","email":"jhope@gitlab.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/opencode-gitlab-auth_1.3.3_1771248786612_0.8805923952185397"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2026-02-16T13:33:06.759Z","publish_time":1771248786759,"_source_registry_name":"default","contributors":[]}},"dist-tags":{"latest":"1.3.3"},"name":"@gitlab/opencode-gitlab-auth","time":{"created":"2026-01-07T20:29:00.873Z","modified":"2026-03-23T17:32:14.878Z","1.2.1":"2026-01-07T20:28:49.789Z","1.2.0":"2026-01-07T19:58:45.357Z","1.3.0":"2026-01-13T09:21:03.088Z","1.3.1":"2026-01-21T16:41:37.638Z","1.3.2":"2026-01-21T16:44:02.683Z","1.3.3":"2026-02-16T13:33:06.759Z"},"readme":"# OpenCode GitLab Auth\n\nA secure OAuth 2.0 and Personal Access Token authentication plugin for [OpenCode](https://opencode.ai) that enables seamless integration with GitLab.com and self-hosted GitLab instances.\n\n[![npm version](https://img.shields.io/npm/v/@gitlab/opencode-gitlab-auth.svg)](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Features\n\n### 🔐 Dual Authentication Methods\n\n- **OAuth 2.0 Flow** - Secure browser-based authentication with automatic token management\n- **Personal Access Token (PAT)** - Simple token-based authentication for automation and CI/CD\n\n### 🛡️ Security First\n\n- **PKCE (Proof Key for Code Exchange)** - Enhanced OAuth security without client secrets\n- **State Parameter** - CSRF attack prevention\n- **Secure Token Storage** - Credentials stored with 600 file permissions\n- **Automatic Token Refresh** - Seamless token renewal via OpenCode's auth system\n- **Rate Limiting** - Built-in protection against abuse (30 requests/minute)\n\n### 🌐 Flexible Instance Support\n\n- GitLab.com (default)\n- Self-hosted GitLab instances\n- Custom instance URL configuration\n\n### 🚀 Developer Experience\n\n- Automatic browser opening for OAuth\n- Local callback server for seamless authorization\n- No manual code copying required\n- Comprehensive error handling and user feedback\n- Debug logging for troubleshooting\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Authentication Methods](#authentication-methods)\n  - [OAuth 2.0 (Recommended)](#oauth-20-recommended)\n  - [Personal Access Token](#personal-access-token)\n- [Configuration](#configuration)\n- [Architecture](#architecture)\n- [API Reference](#api-reference)\n- [Security](#security)\n- [Troubleshooting](#troubleshooting)\n- [Development](#development)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Installation\n\n### Prerequisites\n\n- Node.js 18.0.0 or higher\n- npm 9.0.0 or higher\n- OpenCode installed and configured\n\n### Install via npm\n\n```bash\nnpm install @gitlab/opencode-gitlab-auth\n```\n\n### Install via npm link (Development)\n\n```bash\n# Clone the repository\ngit clone https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git\ncd opencode-gitlab-auth\n\n# Install dependencies\nnpm install\n\n# Build the project\nnpm run build\n\n# Link globally\nnpm link\n\n# In your OpenCode installation, link the plugin\nnpm link @gitlab/opencode-gitlab-auth\n```\n\n## Quick Start\n\n### 1. Configure OpenCode\n\nAdd the plugin to your OpenCode configuration:\n\n```json\n{\n  \"plugins\": [\"@gitlab/opencode-gitlab-auth\"]\n}\n```\n\n### 2. Set Up OAuth (Optional but Recommended)\n\nFor OAuth authentication, you need to register an OAuth application on GitLab:\n\n1. Go to [GitLab User Settings > Applications](https://gitlab.com/-/user_settings/applications)\n2. Create a new application with:\n   - **Name**: `OpenCode GitLab Auth`\n   - **Redirect URI**: `http://127.0.0.1:8080/callback`\n   - **Confidential**: ✅ (checked)\n   - **Scopes**: `api`\n3. Copy the **Application ID** (NOT the secret - PKCE doesn't need it)\n4. Set the environment variable:\n\n```bash\nexport GITLAB_OAUTH_CLIENT_ID=your_application_id_here\n```\n\nOr create a `.env` file:\n\n```bash\nGITLAB_OAUTH_CLIENT_ID=your_application_id_here\n```\n\n### 3. Authenticate\n\nStart OpenCode and use the `/connect` command:\n\n```bash\nopencode\n# In OpenCode:\n/connect\n```\n\nChoose your authentication method:\n\n- **GitLab OAuth** - Browser-based authentication (recommended)\n- **GitLab Personal Access Token** - Token-based authentication\n\n## Authentication Methods\n\n### OAuth 2.0 (Recommended)\n\nOAuth provides the most secure authentication with automatic token refresh and no need to manage long-lived credentials.\n\n#### How It Works\n\n1. **Authorization Request**: OpenCode opens your browser to GitLab's authorization page\n2. **User Consent**: You approve the application's access request\n3. **Callback Handling**: GitLab redirects to a local callback server\n4. **Token Exchange**: The authorization code is exchanged for access and refresh tokens using PKCE\n5. **Secure Storage**: Tokens are stored in `~/.local/share/opencode/auth.json` with 600 permissions\n\n#### OAuth Flow Diagram\n\n```mermaid\nsequenceDiagram\n    participant OpenCode\n    participant Browser\n    participant GitLab\n    participant LocalServer as Local Callback Server\n    participant Storage as Secure Storage\n\n    OpenCode->>Browser: 1. Open Authorization URL<br/>(with PKCE challenge)\n    Browser->>GitLab: 2. Authorization Request\n    GitLab->>Browser: 3. User Approves\n    Browser->>LocalServer: 4. Redirect with Auth Code\n    LocalServer->>GitLab: 5. Token Exchange<br/>(with PKCE verifier)\n    GitLab->>LocalServer: 6. Access + Refresh Tokens\n    LocalServer->>Storage: 7. Save Tokens\n    LocalServer->>OpenCode: 8. Authentication Complete\n```\n\n#### Advantages\n\n- ✅ Most secure method (no long-lived credentials)\n- ✅ Automatic token refresh\n- ✅ Revocable from GitLab settings\n- ✅ No manual token management\n- ✅ PKCE eliminates need for client secrets\n\n#### Requirements\n\n- Custom OAuth application registered on GitLab\n- `GITLAB_OAUTH_CLIENT_ID` environment variable set\n- Browser access for authorization\n\n### Personal Access Token\n\nPAT authentication is simpler but requires manual token management.\n\n#### How to Create a PAT\n\n1. Go to [GitLab User Settings > Access Tokens](https://gitlab.com/-/user_settings/personal_access_tokens)\n2. Create a new token with:\n   - **Name**: `OpenCode`\n   - **Scopes**: `api`\n   - **Expiration**: Set according to your security policy\n3. Copy the token (starts with `glpat-`)\n4. Enter it when prompted by OpenCode\n\n#### Advantages\n\n- ✅ Simple setup (no OAuth app registration)\n- ✅ Works in headless environments\n- ✅ Suitable for CI/CD pipelines\n- ✅ No browser required\n\n#### Disadvantages\n\n- ⚠️ Manual token rotation required\n- ⚠️ Long-lived credentials\n- ⚠️ No automatic refresh\n\n## Configuration\n\n### Environment Variables\n\n| Variable                 | Description           | Required  | Default              |\n| ------------------------ | --------------------- | --------- | -------------------- |\n| `GITLAB_OAUTH_CLIENT_ID` | OAuth application ID  | For OAuth | Bundled ID (limited) |\n| `XDG_DATA_HOME`          | Custom data directory | No        | `~/.local/share`     |\n\n### Storage Locations\n\nCredentials are stored in platform-specific locations:\n\n- **Linux/macOS**: `~/.local/share/opencode/auth.json`\n- **Windows**: `~/.opencode/auth.json`\n- **Custom**: `$XDG_DATA_HOME/opencode/auth.json`\n\nFile permissions are automatically set to `600` (owner read/write only).\n\n### Debug Logging\n\nDebug logs are written to:\n\n- **Linux/macOS**: `~/.local/share/opencode/log/gitlab-auth.log`\n- **Windows**: `~/.opencode/log/gitlab-auth.log`\n\nLogs include:\n\n- Authentication flow steps\n- Token exchange details\n- Error messages and stack traces\n- Timestamps for all events\n\n## Architecture\n\n### Project Structure\n\n```\nopencode-gitlab-auth/\n├── src/\n│   ├── index.ts              # Main plugin entry point\n│   ├── oauth-flow.ts         # OAuth 2.0 flow implementation\n│   ├── callback-server.ts    # Local HTTP server for OAuth callbacks\n│   └── pkce.ts               # PKCE utilities (verifier & challenge)\n├── dist/                     # Compiled JavaScript (generated)\n├── .husky/                   # Git hooks for code quality\n├── package.json\n├── tsconfig.json\n└── README.md\n```\n\n### Core Components\n\n#### 1. Plugin Entry Point (`index.ts`)\n\nThe main plugin that integrates with OpenCode's authentication system.\n\n**Key Functions:**\n\n- `gitlabAuthPlugin()` - Main plugin export implementing OpenCode's `Plugin` interface\n- `debugLog()` - File-based logging that doesn't interfere with UI\n- `getAuthPath()` - Platform-aware auth file path resolution\n- `saveAuthData()` - Secure credential storage with proper permissions\n\n**Exports:**\n\n```typescript\nexport const gitlabAuthPlugin: Plugin;\nexport default gitlabAuthPlugin;\n```\n\n**Authentication Hook:**\n\n```typescript\ninterface AuthHook {\n  provider: 'gitlab';\n  loader: (auth: () => Promise<AuthData>) => Promise<LoaderResult>;\n  methods: [OAuthMethod, PATMethod];\n}\n```\n\n#### 2. OAuth Flow (`oauth-flow.ts`)\n\nImplements the complete OAuth 2.0 authorization code flow with PKCE.\n\n**Class: `GitLabOAuthFlow`**\n\n```typescript\nclass GitLabOAuthFlow {\n  constructor(options: OAuthFlowOptions);\n\n  // Start OAuth authorization\n  async authorize(): Promise<AuthorizationResult>;\n\n  // Exchange authorization code for tokens\n  async exchangeAuthorizationCode(\n    code: string,\n    codeVerifier: string,\n    redirectUri: string\n  ): Promise<OAuthTokens>;\n\n  // Refresh access token\n  async exchangeRefreshToken(refreshToken: string): Promise<OAuthTokens>;\n}\n```\n\n**Interfaces:**\n\n```typescript\ninterface OAuthFlowOptions {\n  instanceUrl: string; // GitLab instance URL\n  clientId: string; // OAuth client ID\n  scopes: string[]; // Requested scopes\n  method: 'auto' | 'code'; // Authorization method\n  timeout?: number; // Timeout in milliseconds\n}\n\ninterface OAuthTokens {\n  access_token: string;\n  refresh_token: string;\n  expires_in: number;\n  token_type: string;\n  scope: string;\n  created_at: number;\n}\n\ninterface AuthorizationResult {\n  code: string; // Authorization code\n  state: string; // CSRF protection state\n  codeVerifier: string; // PKCE verifier\n}\n```\n\n**Flow Steps:**\n\n1. Generate PKCE parameters (verifier & challenge)\n2. Generate random state for CSRF protection\n3. Build authorization URL with parameters\n4. Open browser or provide manual URL\n5. Wait for callback with authorization code\n6. Verify state parameter matches\n7. Exchange code for tokens using PKCE verifier\n8. Return tokens for storage\n\n#### 3. Callback Server (`callback-server.ts`)\n\nLocal HTTP server using Fastify to handle OAuth redirects.\n\n**Class: `CallbackServer`**\n\n```typescript\nclass CallbackServer {\n  constructor(options?: CallbackServerOptions);\n\n  // Start the server\n  async start(): Promise<void>;\n\n  // Wait for OAuth callback\n  async waitForCallback(): Promise<CallbackResult>;\n\n  // Get the actual port being used\n  getPort(): number;\n\n  // Get the full callback URL\n  getCallbackUrl(): string;\n\n  // Close the server\n  async close(): Promise<void>;\n}\n```\n\n**Interfaces:**\n\n```typescript\ninterface CallbackServerOptions {\n  port?: number; // Port to listen on (0 = random)\n  host?: string; // Host to bind to (default: 127.0.0.1)\n  timeout?: number; // Timeout in ms (default: 60000)\n}\n\ninterface CallbackResult {\n  code: string; // Authorization code from GitLab\n  state: string; // State parameter for verification\n}\n```\n\n**Features:**\n\n- **Rate Limiting**: 30 requests per 60 seconds\n- **Error Handling**: Displays user-friendly error pages\n- **Success Page**: Confirms authentication and instructs user\n- **Automatic Cleanup**: Closes server after callback or timeout\n- **Timeout Protection**: Rejects promise after configured timeout\n\n**Callback Route:**\n\n```\nGET /callback?code=xxx&state=yyy\n```\n\nResponse scenarios:\n\n- ✅ Success: Returns HTML success page, resolves promise\n- ❌ Error: Returns HTML error page, rejects promise\n- ⏱️ Timeout: Rejects promise after timeout period\n\n#### 4. PKCE Utilities (`pkce.ts`)\n\nCryptographic functions for OAuth PKCE (Proof Key for Code Exchange).\n\n**Functions:**\n\n```typescript\n// Generate cryptographically secure random string\nfunction generateSecret(length: number = 43): string;\n\n// Generate SHA-256 code challenge from verifier\nfunction generateCodeChallengeFromVerifier(verifier: string): string;\n\n// Internal: Base64 URL encoding (RFC 4648 Section 5)\nfunction base64UrlEncode(buffer: Buffer): string;\n```\n\n**PKCE Flow:**\n\n1. **Code Verifier**: Random 43-character string\n\n   ```typescript\n   const verifier = generateSecret(43);\n   // Example: \"dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk\"\n   ```\n\n2. **Code Challenge**: SHA-256 hash of verifier\n\n   ```typescript\n   const challenge = generateCodeChallengeFromVerifier(verifier);\n   // Example: \"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\"\n   ```\n\n3. **Authorization**: Send challenge to GitLab\n4. **Token Exchange**: Send verifier to prove ownership\n\n**Security:**\n\n- Uses Node.js `crypto` module for secure randomness\n- SHA-256 hashing for challenge generation\n- Base64 URL encoding (RFC 4648) for safe transmission\n- No client secret required\n\n### Component Interactions\n\n```mermaid\ngraph TB\n    OpenCode[OpenCode Core]\n    Plugin[index.ts Plugin]\n    AuthHook[AuthHook<br/>- loader<br/>- methods OAuth & PAT]\n    OAuthFlow[oauth-flow.ts<br/>GitLabOAuthFlow]\n    PATFlow[Direct API Call<br/>/api/v4/user]\n    CallbackServer[callback-server.ts<br/>CallbackServer Fastify HTTP]\n    PKCE[pkce.ts<br/>PKCE Utilities Crypto functions]\n\n    OpenCode -->|Plugin API| Plugin\n    Plugin --> AuthHook\n    AuthHook -->|OAuth Flow| OAuthFlow\n    AuthHook -->|PAT Flow| PATFlow\n    OAuthFlow -->|Uses| CallbackServer\n    OAuthFlow -->|Uses| PKCE\n```\n\n### Data Flow\n\n#### OAuth Authentication Flow\n\n```mermaid\nflowchart TD\n    A[User initiates /connect] --> B[Plugin prompts for instance URL]\n    B --> C[Generate PKCE verifier & challenge]\n    C --> D[Start local callback server port 8080]\n    D --> E[Build authorization URL with:<br/>- client_id<br/>- redirect_uri<br/>- code_challenge SHA-256<br/>- state CSRF token<br/>- scope api]\n    E --> F[Open browser to authorization URL]\n    F --> G[User approves on GitLab]\n    G --> H[GitLab redirects to callback server]\n    H --> I[Callback server receives:<br/>- code authorization code<br/>- state for verification]\n    I --> J[Verify state matches]\n    J --> K[Exchange code for tokens:<br/>POST /oauth/token with:<br/>- code<br/>- code_verifier<br/>- redirect_uri]\n    K --> L[Receive tokens:<br/>- access_token<br/>- refresh_token<br/>- expires_in]\n    L --> M[Save to auth.json with 600 permissions]\n    M --> N[Close callback server]\n    N --> O[Return success to OpenCode]\n```\n\n#### PAT Authentication Flow\n\n```mermaid\nflowchart TD\n    A[User initiates /connect] --> B[Plugin prompts for:<br/>- Instance URL<br/>- Personal Access Token]\n    B --> C[Validate token format<br/>starts with glpat-]\n    C --> D[Test token with API call:<br/>GET /api/v4/user<br/>Authorization: Bearer token]\n    D --> E{Successful?}\n    E -->|Yes| F[Save token to auth.json]\n    F --> G[Return success]\n    E -->|No| H[Return error]\n    H --> I[Prompt user to try again]\n```\n\n### Security Architecture\n\n#### Token Storage\n\n```\n~/.local/share/opencode/auth.json\n{\n  \"gitlab\": {\n    \"type\": \"oauth\",\n    \"access\": \"ya29.a0AfH6SMBx...\",\n    \"refresh\": \"1//0gHZPQhYjIsN...\",\n    \"expires\": 1735948800000,\n    \"enterpriseUrl\": \"https://gitlab.com\"\n  }\n}\n```\n\n**Security Measures:**\n\n- File permissions: `600` (owner read/write only)\n- JSON format for easy parsing\n- Separate storage per provider\n- Includes expiration timestamp\n- Enterprise URL for multi-instance support\n\n#### PKCE Security\n\nTraditional OAuth requires a client secret, which can't be securely stored in desktop applications. PKCE solves this:\n\n**Without PKCE (Insecure):**\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant AuthServer as Authorization Server\n\n    Client->>AuthServer: client_id + client_secret\n    Note over Client,AuthServer: Problem: Secret can be extracted from application\n```\n\n**With PKCE (Secure):**\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant AuthServer as Authorization Server\n\n    Note over Client: 1. Generate random verifier\n    Client->>AuthServer: 2. Send SHA-256(verifier) as challenge\n    Note over AuthServer: 3. Store challenge\n    Client->>AuthServer: 4. Send verifier to prove ownership\n    Note over AuthServer: 5. Verify SHA-256(verifier) == challenge\n```\n\n**Benefits:**\n\n- No client secret needed\n- Verifier never transmitted during authorization\n- Challenge can't be reversed to get verifier\n- Protects against authorization code interception\n\n#### State Parameter\n\nPrevents CSRF attacks where an attacker tricks a user into authorizing their malicious app:\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant GitLab\n\n    Note over Client: 1. Generate random state: \"abc123xyz\"\n    Note over Client: 2. Store state locally\n    Client->>GitLab: 3. Send state in authorization URL\n    GitLab->>Client: 4. Include state in redirect\n    Note over Client: 5. Verify returned state matches stored state\n    alt State mismatch\n        Note over Client: 6. Reject (possible attack)\n    else State matches\n        Note over Client: 6. Continue authentication\n    end\n```\n\n#### Rate Limiting\n\nCallback server includes rate limiting to prevent abuse:\n\n```typescript\n{\n  max: 30,              // Maximum requests\n  timeWindow: 60000     // Per 60 seconds\n}\n```\n\nProtects against:\n\n- Brute force attacks\n- Denial of service\n- Callback flooding\n\n## API Reference\n\n### Plugin Export\n\n```typescript\nimport gitlabAuthPlugin from '@gitlab/opencode-gitlab-auth';\n\n// Default export\nexport default gitlabAuthPlugin;\n\n// Named export\nexport const gitlabAuthPlugin: Plugin;\n```\n\n### TypeScript Types\n\n```typescript\n// OAuth Flow Options\ninterface OAuthFlowOptions {\n  instanceUrl: string;\n  clientId: string;\n  scopes: string[];\n  method: 'auto' | 'code';\n  timeout?: number;\n}\n\n// OAuth Tokens Response\ninterface OAuthTokens {\n  access_token: string;\n  refresh_token: string;\n  expires_in: number;\n  token_type: string;\n  scope: string;\n  created_at: number;\n}\n\n// Callback Server Options\ninterface CallbackServerOptions {\n  port?: number;\n  host?: string;\n  timeout?: number;\n}\n\n// Callback Result\ninterface CallbackResult {\n  code: string;\n  state: string;\n}\n```\n\n### OpenCode Integration\n\nThe plugin implements OpenCode's `Plugin` interface:\n\n```typescript\ninterface Plugin {\n  auth: AuthHook;\n}\n\ninterface AuthHook {\n  provider: string;\n  loader: (auth: () => Promise<AuthData>) => Promise<LoaderResult>;\n  methods: AuthMethod[];\n}\n```\n\n## Security\n\n### Best Practices\n\n1. **Use OAuth over PAT** when possible for better security\n2. **Rotate PATs regularly** if using token authentication\n3. **Never commit** credentials or tokens to version control\n4. **Use environment variables** for OAuth client IDs\n5. **Review authorized applications** periodically in GitLab settings\n6. **Monitor auth logs** for suspicious activity\n\n### Security Features\n\n| Feature         | Description                 | Benefit                               |\n| --------------- | --------------------------- | ------------------------------------- |\n| PKCE            | Proof Key for Code Exchange | Eliminates need for client secrets    |\n| State Parameter | Random CSRF token           | Prevents cross-site request forgery   |\n| Secure Storage  | 600 file permissions        | Protects credentials from other users |\n| Token Refresh   | Automatic renewal           | Reduces exposure window               |\n| Rate Limiting   | 30 req/min on callback      | Prevents abuse                        |\n| HTTPS Only      | Enforced for GitLab API     | Prevents man-in-the-middle attacks    |\n\n### Threat Model\n\n**Protected Against:**\n\n- ✅ Authorization code interception (PKCE)\n- ✅ CSRF attacks (state parameter)\n- ✅ Token theft from filesystem (600 permissions)\n- ✅ Brute force attacks (rate limiting)\n- ✅ Man-in-the-middle (HTTPS enforcement)\n\n**Not Protected Against:**\n\n- ⚠️ Malware with root/admin access\n- ⚠️ Physical access to unlocked machine\n- ⚠️ Compromised GitLab account\n- ⚠️ Social engineering attacks\n\n### Reporting Security Issues\n\nPlease report security vulnerabilities to the maintainers privately. Do not open public issues for security concerns.\n\n## Troubleshooting\n\n### Common Issues\n\n#### OAuth: Browser doesn't open\n\n**Symptoms:**\n\n- Authorization URL displayed but browser doesn't open\n- Manual URL copy required\n\n**Solutions:**\n\n1. Check if `open` command is available:\n\n   ```bash\n   # macOS\n   which open\n\n   # Linux\n   which xdg-open\n\n   # Windows\n   where start\n   ```\n\n2. Manually open the URL displayed in terminal\n\n3. Check firewall settings for port 8080\n\n#### OAuth: Callback timeout\n\n**Symptoms:**\n\n- \"OAuth callback timeout\" error after 2 minutes\n- Browser shows success but OpenCode shows failure\n\n**Solutions:**\n\n1. Check if port 8080 is available:\n\n   ```bash\n   lsof -i :8080  # macOS/Linux\n   netstat -ano | findstr :8080  # Windows\n   ```\n\n2. Ensure no firewall blocking localhost:8080\n\n3. Try increasing timeout in code (requires rebuild)\n\n4. Check debug logs:\n\n   ```bash\n   tail -f ~/.local/share/opencode/log/gitlab-auth.log\n   ```\n\n#### OAuth: Invalid client\n\n**Symptoms:**\n\n- \"The client identifier provided is invalid\" error\n- OAuth app not found\n\n**Solutions:**\n\n1. Verify `GITLAB_OAUTH_CLIENT_ID` is set correctly:\n\n   ```bash\n   echo $GITLAB_OAUTH_CLIENT_ID\n   ```\n\n2. Check OAuth app settings on GitLab:\n   - Redirect URI must be: `http://127.0.0.1:8080/callback`\n   - Application must be \"Confidential\"\n   - Scope must include \"api\"\n\n3. Ensure OAuth app is not expired or revoked\n\n#### PAT: Authentication failed\n\n**Symptoms:**\n\n- \"Authentication failed\" when entering PAT\n- Token validation fails\n\n**Solutions:**\n\n1. Verify token format:\n   - Must start with `glpat-`\n   - No extra spaces or newlines\n\n2. Check token scopes:\n   - Must have `api` scope\n   - Check in GitLab Settings > Access Tokens\n\n3. Verify token is not expired\n\n4. Test token manually:\n\n   ```bash\n   curl -H \"Authorization: Bearer glpat-xxx\" \\\n     https://gitlab.com/api/v4/user\n   ```\n\n#### Self-hosted GitLab issues\n\n**Symptoms:**\n\n- Connection errors with self-hosted instance\n- SSL certificate errors\n\n**Solutions:**\n\n1. Verify instance URL format:\n\n   ```\n   ✅ https://gitlab.example.com\n   ❌ https://gitlab.example.com/\n   ❌ gitlab.example.com\n   ```\n\n2. Check SSL certificate:\n\n   ```bash\n   curl -v https://gitlab.example.com/api/v4/version\n   ```\n\n3. For self-signed certificates (not recommended):\n\n   ```bash\n   export NODE_TLS_REJECT_UNAUTHORIZED=0\n   ```\n\n4. Ensure instance is accessible:\n\n   ```bash\n   ping gitlab.example.com\n   ```\n\n### Debug Logging\n\nEnable detailed logging by checking the log file:\n\n```bash\n# View logs in real-time\ntail -f ~/.local/share/opencode/log/gitlab-auth.log\n\n# View last 50 lines\ntail -n 50 ~/.local/share/opencode/log/gitlab-auth.log\n\n# Search for errors\ngrep -i error ~/.local/share/opencode/log/gitlab-auth.log\n```\n\nLog entries include:\n\n- Timestamp\n- Event description\n- Relevant data (sanitized)\n- Error stack traces\n\n### Getting Help\n\n1. **Check existing issues**: [GitLab Issues](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues)\n2. **Review debug logs**: `~/.local/share/opencode/log/gitlab-auth.log`\n3. **Open a new issue**: Include logs and steps to reproduce\n4. **Community support**: OpenCode Discord/Slack\n\n## Development\n\n### Setup Development Environment\n\n```bash\n# Clone repository\ngit clone https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git\ncd opencode-gitlab-auth\n\n# Install dependencies\nnpm install\n\n# Set up Git hooks\nnpm run prepare\n\n# Build project\nnpm run build\n```\n\n### Available Scripts\n\n| Script                 | Description                      |\n| ---------------------- | -------------------------------- |\n| `npm run build`        | Compile TypeScript to JavaScript |\n| `npm run clean`        | Remove dist/ directory           |\n| `npm run rebuild`      | Clean and build                  |\n| `npm run lint`         | Check code style                 |\n| `npm run lint:fix`     | Fix code style issues            |\n| `npm run format`       | Format code with Prettier        |\n| `npm run format:check` | Check code formatting            |\n| `npm run prepare`      | Install Git hooks                |\n\n### Code Style\n\n- **TypeScript**: Strict mode enabled\n- **Indentation**: 2 spaces\n- **Quotes**: Single quotes\n- **Semicolons**: Required\n- **Line length**: 100 characters max\n- **Naming**:\n  - camelCase for variables/functions\n  - PascalCase for classes/interfaces\n  - UPPER_CASE for constants\n\n### Git Workflow\n\n1. **Create feature branch**:\n\n   ```bash\n   git checkout -b feat/your-feature\n   ```\n\n2. **Make changes** and commit:\n\n   ```bash\n   git add .\n   git commit -m \"feat: add new feature\"\n   ```\n\n3. **Push and create MR**:\n\n   ```bash\n   git push origin feat/your-feature\n   ```\n\n### Commit Message Format\n\nFollow [Conventional Commits](https://www.conventionalcommits.org/):\n\n```\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n```\n\n**Types:**\n\n- `feat`: New feature\n- `fix`: Bug fix\n- `docs`: Documentation\n- `style`: Code style (formatting)\n- `refactor`: Code refactoring\n- `perf`: Performance improvement\n- `test`: Tests\n- `build`: Build system\n- `ci`: CI/CD\n- `chore`: Maintenance\n\n**Examples:**\n\n```bash\nfeat(oauth): add support for custom redirect URIs\nfix(server): resolve callback timeout issue\ndocs: update installation instructions\n```\n\n### Testing\n\nCurrently, testing is manual. To test changes:\n\n```bash\n# Build\nnpm run build\n\n# Link locally\nnpm link\n\n# Test with OpenCode\nopencode\n# Use /connect command\n```\n\n**Test Checklist:**\n\n- [ ] OAuth flow completes successfully\n- [ ] PAT authentication works\n- [ ] Token refresh works (wait for expiration)\n- [ ] Self-hosted GitLab instances work\n- [ ] Error handling displays correctly\n- [ ] Debug logs are written\n- [ ] File permissions are correct (600)\n\n### Release Process\n\nReleases are automated using semantic-release:\n\n1. Commit changes following conventional commits\n2. Push to `main` branch\n3. CI/CD pipeline runs:\n   - Lints code\n   - Builds project\n   - Determines version bump\n   - Updates CHANGELOG.md\n   - Creates Git tag\n   - Publishes to npm\n\nVersion bumps:\n\n- `feat:` → Minor version (1.0.0 → 1.1.0)\n- `fix:` → Patch version (1.0.0 → 1.0.1)\n- `feat!:` or `BREAKING CHANGE:` → Major version (1.0.0 → 2.0.0)\n\n## Contributing\n\nContributions are welcome! Please see our [Contributing Guide](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/blob/main/CONTRIBUTING.md) for detailed guidelines on:\n\n- Code style and conventions\n- Development workflow\n- Testing requirements\n- Submitting merge requests\n- Developer Certificate of Origin and License\n\n**Quick Start for Contributors**:\n\n1. **Commit Messages**: Use conventional commits format\n\n   ```\n   feat(scope): add new feature\n   fix(scope): fix bug\n   docs(scope): update documentation\n   ```\n\n2. **Code Quality**: Ensure all checks pass\n\n   ```bash\n   npm run lint\n   npm run format:check\n   npm run build\n   ```\n\n3. **Testing**: Manual testing via `npm link` and OpenCode integration\n\n## FAQ\n\n### Q: Do I need to register an OAuth app?\n\n**A:** For best experience\n\n---\n\n## Assistant\n\n, yes. The bundled client ID has limitations. Register your own app at [GitLab Applications](https://gitlab.com/-/user_settings/applications).\n\n### Q: Can I use this with GitLab self-hosted?\n\n**A:** Yes! Enter your instance URL when prompted (e.g., `https://gitlab.company.com`).\n\n### Q: How do I revoke access?\n\n**A:**\n\n- **OAuth**: Go to GitLab Settings > Applications > Authorized Applications\n- **PAT**: Go to GitLab Settings > Access Tokens > Revoke\n\n### Q: Where are my credentials stored?\n\n**A:** In `~/.local/share/opencode/auth.json` with 600 permissions (owner only).\n\n### Q: Can I use multiple GitLab accounts?\n\n**A:** Currently, only one account per instance is supported. You'll need to re-authenticate to switch accounts.\n\n### Q: Does this work offline?\n\n**A:** No, authentication requires internet access to GitLab. However, once authenticated, OpenCode may cache some data.\n\n### Q: Is my token secure?\n\n**A:** Tokens are stored with 600 file permissions and never transmitted except to GitLab's API over HTTPS. However, any process running as your user can access them.\n\n### Q: Can I use this in CI/CD?\n\n**A:** Yes, use Personal Access Token authentication. OAuth requires browser interaction.\n\n### Q: How long do tokens last?\n\n**A:** OAuth access tokens expire after 2 hours but are automatically refreshed. PATs last until their configured expiration date.\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history and release notes.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\nCopyright (c) 2025 OpenCode GitLab Auth Contributors\n\n## Acknowledgments\n\n- Inspired by [gitlab-vscode-extension](https://gitlab.com/gitlab-org/gitlab-vscode-extension)\n- OAuth patterns from [gitlab-lsp](https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp)\n- Built for [OpenCode](https://opencode.ai)\n\n## Links\n\n- [GitLab Repository](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth)\n- [npm Package](https://www.npmjs.com/package/@gitlab/opencode-gitlab-auth)\n- [Issue Tracker](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/issues)\n- [Contributing Guide](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/blob/main/CONTRIBUTING.md)\n- [Changelog](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/blob/main/CHANGELOG.md)\n- [Agent Guidelines](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth/-/blob/main/AGENTS.md)\n\n## Acknowledgments\n\nThis project is built for:\n\n- [OpenCode](https://opencode.ai)\n- [GitLab Duo](https://about.gitlab.com/gitlab-duo/)\n- [GitLab OAuth](https://docs.gitlab.com/ee/api/oauth2.html)\n\n---\n\n**Made with ❤️ for the OpenCode community**\n\n---","users":{}}