diff --git a/.editorconfig b/.editorconfig index 6235f134..58154565 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,163 +1,163 @@ -# EditorConfig is awesome: https://EditorConfig.org - -root = true - -[*] -charset = utf-8 -indent_style = tab -indent_size = 4 -insert_final_newline = true -trim_trailing_whitespace = true -end_of_line = lf - -[*.{cs,csx}] -indent_style = tab - -[*.{json,yml,yaml}] -indent_style = space -indent_size = 2 - -[*.{js,ts,jsx,tsx,html,css,scss}] -indent_style = space -indent_size = 2 - -[*.md] -trim_trailing_whitespace = false - -# ───────────────────────────────────────────────────────────────────── -# Backend security analyzers (Roslyn / NetAnalyzers) -# ───────────────────────────────────────────────────────────────────── -# We elevate the security-relevant rule families to `error` so a -# regression breaks the build. Style/perf/naming rules are intentionally -# left at their defaults — see security-hardening.md for the campaign -# that closed the existing security findings; this configuration is the -# guardrail to keep new ones from landing silently. -# -# Coverage: -# CA21xx (general security: command/SQL injection, format-string) -# CA3xxx (data-flow taint analysis: XSS, XPath, LDAP, XML, ReDoS) -# CA53xx (cryptography & PKI: weak ciphers, weak hashes, weak random, -# cert validation, key length, padding) -# -# When a rule fires legitimately for a justified reason, suppress at -# the call site with a `#pragma` + comment explaining why — never -# globally relax the rule here. -[*.cs] -# Injection / format-string -dotnet_diagnostic.CA2100.severity = error # SQL queries built from user input -dotnet_diagnostic.CA2109.severity = error # event-handler exposed publicly -dotnet_diagnostic.CA2153.severity = error # corrupted-state exception handling -dotnet_diagnostic.CA2300.severity = error # BinaryFormatter without bind -dotnet_diagnostic.CA2301.severity = error # BinaryFormatter without bind -dotnet_diagnostic.CA2302.severity = error # BinaryFormatter without bind -dotnet_diagnostic.CA2305.severity = error # LosFormatter -dotnet_diagnostic.CA2310.severity = error # NetDataContractSerializer -dotnet_diagnostic.CA2311.severity = error # NetDataContractSerializer without bind -dotnet_diagnostic.CA2312.severity = error # NetDataContractSerializer without bind -dotnet_diagnostic.CA2315.severity = error # ObjectStateFormatter -dotnet_diagnostic.CA2321.severity = error # JavaScriptSerializer with SimpleTypeResolver -dotnet_diagnostic.CA2322.severity = error # JavaScriptSerializer ensure-not-Simple -dotnet_diagnostic.CA2326.severity = error # TypeNameHandling values other than None -dotnet_diagnostic.CA2327.severity = error # insecure JsonSerializerSettings -dotnet_diagnostic.CA2328.severity = error # insecure JsonSerializerSettings (taint) -dotnet_diagnostic.CA2329.severity = error # JsonSerializer w/ insecure settings -dotnet_diagnostic.CA2330.severity = error # JsonSerializer w/ insecure settings (taint) -dotnet_diagnostic.CA2350.severity = error # DataTable.ReadXml untrusted -dotnet_diagnostic.CA2351.severity = error # DataSet.ReadXml untrusted -dotnet_diagnostic.CA2352.severity = error # unsafe DataSet/Table in serialized type -dotnet_diagnostic.CA2353.severity = error # unsafe DataSet/Table in serializable type -dotnet_diagnostic.CA2354.severity = error # unsafe DataSet/Table in deserialized graph -dotnet_diagnostic.CA2355.severity = error # unsafe DataSet/Table in deserialized graph -dotnet_diagnostic.CA2356.severity = error # unsafe DataSet/Table in WCF type -dotnet_diagnostic.CA2361.severity = error # autogen class containing DataSet -dotnet_diagnostic.CA2362.severity = error # unsafe DataSet/Table in autogen class - -# Data-flow / taint analysis (CA3xxx) -dotnet_diagnostic.CA3001.severity = error # SQL injection -dotnet_diagnostic.CA3002.severity = error # XSS -dotnet_diagnostic.CA3003.severity = error # file-path injection -dotnet_diagnostic.CA3004.severity = error # information-exposure-through-exception -dotnet_diagnostic.CA3005.severity = error # LDAP injection -dotnet_diagnostic.CA3006.severity = error # process-command injection -dotnet_diagnostic.CA3007.severity = error # open-redirect -dotnet_diagnostic.CA3008.severity = error # XPath injection -dotnet_diagnostic.CA3009.severity = error # XML injection -dotnet_diagnostic.CA3010.severity = error # XAML injection -dotnet_diagnostic.CA3011.severity = error # DLL injection -dotnet_diagnostic.CA3012.severity = error # ReDoS (regex injection) -dotnet_diagnostic.CA3061.severity = error # XmlDocument insecure -dotnet_diagnostic.CA3075.severity = error # insecure DTD processing -dotnet_diagnostic.CA3076.severity = error # insecure XSLT script processing -dotnet_diagnostic.CA3077.severity = error # insecure XML processing in API -dotnet_diagnostic.CA3147.severity = error # missing ValidateAntiForgeryToken - -# Crypto / PKI (CA53xx) -dotnet_diagnostic.CA5350.severity = error # weak cryptographic algorithm -dotnet_diagnostic.CA5351.severity = error # broken cryptographic algorithm -dotnet_diagnostic.CA5358.severity = error # unsafe cipher mode -dotnet_diagnostic.CA5359.severity = error # certificate validation disabled -dotnet_diagnostic.CA5360.severity = error # dangerous deserialize call -dotnet_diagnostic.CA5361.severity = error # SChannel encryption disabled -dotnet_diagnostic.CA5362.severity = error # potential reference-cycle in deserialize -dotnet_diagnostic.CA5363.severity = error # request validation disabled -dotnet_diagnostic.CA5364.severity = error # deprecated security protocol -dotnet_diagnostic.CA5365.severity = error # disable HTTP-header checking -dotnet_diagnostic.CA5366.severity = error # use XmlReader for DataSet read -dotnet_diagnostic.CA5367.severity = error # mutable serializable types -dotnet_diagnostic.CA5368.severity = error # set ViewStateUserKey for AspNet -dotnet_diagnostic.CA5369.severity = error # use XmlReader for Deserialize -dotnet_diagnostic.CA5370.severity = error # use XmlReader for validating -dotnet_diagnostic.CA5371.severity = error # use XmlReader for schema-read -dotnet_diagnostic.CA5372.severity = error # use XmlReader for XPathDocument -dotnet_diagnostic.CA5373.severity = error # obsolete key derivation function -dotnet_diagnostic.CA5374.severity = error # XslTransform unsafe -dotnet_diagnostic.CA5375.severity = error # account SAS token -dotnet_diagnostic.CA5376.severity = error # SharedAccessProtocol HttpsOnly -dotnet_diagnostic.CA5377.severity = error # container-level access policy -dotnet_diagnostic.CA5378.severity = error # disable ServicePointManagerSecurityProtocols -dotnet_diagnostic.CA5379.severity = error # weak key-derivation algorithm -dotnet_diagnostic.CA5380.severity = error # do not add cert to root store -dotnet_diagnostic.CA5381.severity = error # ensure cert added to root store -dotnet_diagnostic.CA5382.severity = error # use secure cookies in ASP.NET Core -dotnet_diagnostic.CA5383.severity = error # ensure secure cookies in ASP.NET Core -dotnet_diagnostic.CA5384.severity = error # do not use DSA -dotnet_diagnostic.CA5385.severity = error # use RSA with sufficient key size -dotnet_diagnostic.CA5386.severity = error # avoid hardcoding SecurityProtocolType value -dotnet_diagnostic.CA5387.severity = error # weak iteration count for KDF -dotnet_diagnostic.CA5388.severity = error # ensure sufficient iteration count for KDF -dotnet_diagnostic.CA5389.severity = error # do not add archive item path to target -dotnet_diagnostic.CA5390.severity = error # do not hard-code encryption key -dotnet_diagnostic.CA5391.severity = error # use anti-forgery tokens in ASP.NET Core MVC -dotnet_diagnostic.CA5392.severity = error # use DefaultDllImportSearchPaths -dotnet_diagnostic.CA5393.severity = error # do not use unsafe DllImportSearchPath -dotnet_diagnostic.CA5394.severity = error # do not use insecure randomness -dotnet_diagnostic.CA5395.severity = error # missing HttpVerb attribute on action methods -dotnet_diagnostic.CA5396.severity = error # set HttpOnly to true for HttpCookie -dotnet_diagnostic.CA5397.severity = error # do not use deprecated SslProtocols values -dotnet_diagnostic.CA5398.severity = error # avoid hardcoded SslProtocols -dotnet_diagnostic.CA5399.severity = error # HttpClient with disabled cert revocation -dotnet_diagnostic.CA5400.severity = error # ensure cert revocation enabled on HttpClient -dotnet_diagnostic.CA5401.severity = error # SymmetricAlgorithm with non-default IV -dotnet_diagnostic.CA5402.severity = error # CreateEncryptor with non-default IV -dotnet_diagnostic.CA5403.severity = error # do not hard-code certificate - -# ───────────────────────────────────────────────────────────────────── -# Dead-code surfacing (Roslyn IDE analyzers) -# ───────────────────────────────────────────────────────────────────── -# These rules surface unused private members + unread fields + unused -# parameters as warnings. Not elevated to error to avoid CI failures -# on legitimate WIP — but the warnings make orphan code visible in -# review + during `dotnet build` runs (and via the `cleanup:check` -# pattern used in the frontend workspaces). -dotnet_diagnostic.IDE0051.severity = warning # unused private member -dotnet_diagnostic.IDE0052.severity = warning # read-but-never-used private member -dotnet_diagnostic.IDE0060.severity = suggestion # unused parameter (lots of public APIs satisfy interfaces, keep noisier) - -# Test projects must reproduce protocol-defined cryptographic primitives -# (TOTP via HMACSHA1 per RFC 6238, etc.) to exercise real auth flows. -# These projects don't ship in the runtime image, so the security-rule -# noise is more harmful than the rule itself. Production code paths are -# still covered by the rules above. -[{**/Modgud.Api.Tests/**.cs,**/Modgud.Tests.Unit/**.cs}] -dotnet_diagnostic.CA5350.severity = suggestion -dotnet_diagnostic.CA5351.severity = suggestion +# EditorConfig is awesome: https://EditorConfig.org + +root = true + +[*] +charset = utf-8 +indent_style = tab +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf + +[*.{cs,csx}] +indent_style = tab + +[*.{json,yml,yaml}] +indent_style = space +indent_size = 2 + +[*.{js,ts,jsx,tsx,html,css,scss}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +# ───────────────────────────────────────────────────────────────────── +# Backend security analyzers (Roslyn / NetAnalyzers) +# ───────────────────────────────────────────────────────────────────── +# We elevate the security-relevant rule families to `error` so a +# regression breaks the build. Style/perf/naming rules are intentionally +# left at their defaults — see security-hardening.md for the campaign +# that closed the existing security findings; this configuration is the +# guardrail to keep new ones from landing silently. +# +# Coverage: +# CA21xx (general security: command/SQL injection, format-string) +# CA3xxx (data-flow taint analysis: XSS, XPath, LDAP, XML, ReDoS) +# CA53xx (cryptography & PKI: weak ciphers, weak hashes, weak random, +# cert validation, key length, padding) +# +# When a rule fires legitimately for a justified reason, suppress at +# the call site with a `#pragma` + comment explaining why — never +# globally relax the rule here. +[*.cs] +# Injection / format-string +dotnet_diagnostic.CA2100.severity = error # SQL queries built from user input +dotnet_diagnostic.CA2109.severity = error # event-handler exposed publicly +dotnet_diagnostic.CA2153.severity = error # corrupted-state exception handling +dotnet_diagnostic.CA2300.severity = error # BinaryFormatter without bind +dotnet_diagnostic.CA2301.severity = error # BinaryFormatter without bind +dotnet_diagnostic.CA2302.severity = error # BinaryFormatter without bind +dotnet_diagnostic.CA2305.severity = error # LosFormatter +dotnet_diagnostic.CA2310.severity = error # NetDataContractSerializer +dotnet_diagnostic.CA2311.severity = error # NetDataContractSerializer without bind +dotnet_diagnostic.CA2312.severity = error # NetDataContractSerializer without bind +dotnet_diagnostic.CA2315.severity = error # ObjectStateFormatter +dotnet_diagnostic.CA2321.severity = error # JavaScriptSerializer with SimpleTypeResolver +dotnet_diagnostic.CA2322.severity = error # JavaScriptSerializer ensure-not-Simple +dotnet_diagnostic.CA2326.severity = error # TypeNameHandling values other than None +dotnet_diagnostic.CA2327.severity = error # insecure JsonSerializerSettings +dotnet_diagnostic.CA2328.severity = error # insecure JsonSerializerSettings (taint) +dotnet_diagnostic.CA2329.severity = error # JsonSerializer w/ insecure settings +dotnet_diagnostic.CA2330.severity = error # JsonSerializer w/ insecure settings (taint) +dotnet_diagnostic.CA2350.severity = error # DataTable.ReadXml untrusted +dotnet_diagnostic.CA2351.severity = error # DataSet.ReadXml untrusted +dotnet_diagnostic.CA2352.severity = error # unsafe DataSet/Table in serialized type +dotnet_diagnostic.CA2353.severity = error # unsafe DataSet/Table in serializable type +dotnet_diagnostic.CA2354.severity = error # unsafe DataSet/Table in deserialized graph +dotnet_diagnostic.CA2355.severity = error # unsafe DataSet/Table in deserialized graph +dotnet_diagnostic.CA2356.severity = error # unsafe DataSet/Table in WCF type +dotnet_diagnostic.CA2361.severity = error # autogen class containing DataSet +dotnet_diagnostic.CA2362.severity = error # unsafe DataSet/Table in autogen class + +# Data-flow / taint analysis (CA3xxx) +dotnet_diagnostic.CA3001.severity = error # SQL injection +dotnet_diagnostic.CA3002.severity = error # XSS +dotnet_diagnostic.CA3003.severity = error # file-path injection +dotnet_diagnostic.CA3004.severity = error # information-exposure-through-exception +dotnet_diagnostic.CA3005.severity = error # LDAP injection +dotnet_diagnostic.CA3006.severity = error # process-command injection +dotnet_diagnostic.CA3007.severity = error # open-redirect +dotnet_diagnostic.CA3008.severity = error # XPath injection +dotnet_diagnostic.CA3009.severity = error # XML injection +dotnet_diagnostic.CA3010.severity = error # XAML injection +dotnet_diagnostic.CA3011.severity = error # DLL injection +dotnet_diagnostic.CA3012.severity = error # ReDoS (regex injection) +dotnet_diagnostic.CA3061.severity = error # XmlDocument insecure +dotnet_diagnostic.CA3075.severity = error # insecure DTD processing +dotnet_diagnostic.CA3076.severity = error # insecure XSLT script processing +dotnet_diagnostic.CA3077.severity = error # insecure XML processing in API +dotnet_diagnostic.CA3147.severity = error # missing ValidateAntiForgeryToken + +# Crypto / PKI (CA53xx) +dotnet_diagnostic.CA5350.severity = error # weak cryptographic algorithm +dotnet_diagnostic.CA5351.severity = error # broken cryptographic algorithm +dotnet_diagnostic.CA5358.severity = error # unsafe cipher mode +dotnet_diagnostic.CA5359.severity = error # certificate validation disabled +dotnet_diagnostic.CA5360.severity = error # dangerous deserialize call +dotnet_diagnostic.CA5361.severity = error # SChannel encryption disabled +dotnet_diagnostic.CA5362.severity = error # potential reference-cycle in deserialize +dotnet_diagnostic.CA5363.severity = error # request validation disabled +dotnet_diagnostic.CA5364.severity = error # deprecated security protocol +dotnet_diagnostic.CA5365.severity = error # disable HTTP-header checking +dotnet_diagnostic.CA5366.severity = error # use XmlReader for DataSet read +dotnet_diagnostic.CA5367.severity = error # mutable serializable types +dotnet_diagnostic.CA5368.severity = error # set ViewStateUserKey for AspNet +dotnet_diagnostic.CA5369.severity = error # use XmlReader for Deserialize +dotnet_diagnostic.CA5370.severity = error # use XmlReader for validating +dotnet_diagnostic.CA5371.severity = error # use XmlReader for schema-read +dotnet_diagnostic.CA5372.severity = error # use XmlReader for XPathDocument +dotnet_diagnostic.CA5373.severity = error # obsolete key derivation function +dotnet_diagnostic.CA5374.severity = error # XslTransform unsafe +dotnet_diagnostic.CA5375.severity = error # account SAS token +dotnet_diagnostic.CA5376.severity = error # SharedAccessProtocol HttpsOnly +dotnet_diagnostic.CA5377.severity = error # container-level access policy +dotnet_diagnostic.CA5378.severity = error # disable ServicePointManagerSecurityProtocols +dotnet_diagnostic.CA5379.severity = error # weak key-derivation algorithm +dotnet_diagnostic.CA5380.severity = error # do not add cert to root store +dotnet_diagnostic.CA5381.severity = error # ensure cert added to root store +dotnet_diagnostic.CA5382.severity = error # use secure cookies in ASP.NET Core +dotnet_diagnostic.CA5383.severity = error # ensure secure cookies in ASP.NET Core +dotnet_diagnostic.CA5384.severity = error # do not use DSA +dotnet_diagnostic.CA5385.severity = error # use RSA with sufficient key size +dotnet_diagnostic.CA5386.severity = error # avoid hardcoding SecurityProtocolType value +dotnet_diagnostic.CA5387.severity = error # weak iteration count for KDF +dotnet_diagnostic.CA5388.severity = error # ensure sufficient iteration count for KDF +dotnet_diagnostic.CA5389.severity = error # do not add archive item path to target +dotnet_diagnostic.CA5390.severity = error # do not hard-code encryption key +dotnet_diagnostic.CA5391.severity = error # use anti-forgery tokens in ASP.NET Core MVC +dotnet_diagnostic.CA5392.severity = error # use DefaultDllImportSearchPaths +dotnet_diagnostic.CA5393.severity = error # do not use unsafe DllImportSearchPath +dotnet_diagnostic.CA5394.severity = error # do not use insecure randomness +dotnet_diagnostic.CA5395.severity = error # missing HttpVerb attribute on action methods +dotnet_diagnostic.CA5396.severity = error # set HttpOnly to true for HttpCookie +dotnet_diagnostic.CA5397.severity = error # do not use deprecated SslProtocols values +dotnet_diagnostic.CA5398.severity = error # avoid hardcoded SslProtocols +dotnet_diagnostic.CA5399.severity = error # HttpClient with disabled cert revocation +dotnet_diagnostic.CA5400.severity = error # ensure cert revocation enabled on HttpClient +dotnet_diagnostic.CA5401.severity = error # SymmetricAlgorithm with non-default IV +dotnet_diagnostic.CA5402.severity = error # CreateEncryptor with non-default IV +dotnet_diagnostic.CA5403.severity = error # do not hard-code certificate + +# ───────────────────────────────────────────────────────────────────── +# Dead-code surfacing (Roslyn IDE analyzers) +# ───────────────────────────────────────────────────────────────────── +# These rules surface unused private members + unread fields + unused +# parameters as warnings. Not elevated to error to avoid CI failures +# on legitimate WIP — but the warnings make orphan code visible in +# review + during `dotnet build` runs (and via the `cleanup:check` +# pattern used in the frontend workspaces). +dotnet_diagnostic.IDE0051.severity = warning # unused private member +dotnet_diagnostic.IDE0052.severity = warning # read-but-never-used private member +dotnet_diagnostic.IDE0060.severity = suggestion # unused parameter (lots of public APIs satisfy interfaces, keep noisier) + +# Test projects must reproduce protocol-defined cryptographic primitives +# (TOTP via HMACSHA1 per RFC 6238, etc.) to exercise real auth flows. +# These projects don't ship in the runtime image, so the security-rule +# noise is more harmful than the rule itself. Production code paths are +# still covered by the rules above. +[{**/Modgud.Api.Tests/**.cs,**/Modgud.Tests.Unit/**.cs}] +dotnet_diagnostic.CA5350.severity = suggestion +dotnet_diagnostic.CA5351.severity = suggestion diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a69814e4..521709db 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,128 +1,128 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -bwi@cocoar.dev. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +bwi@cocoar.dev. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/LICENSE b/LICENSE index a7f77c8b..4997aea2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,201 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2025 COCOAR e.U. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2025 COCOAR e.U. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE index 29f89323..60cbc1cb 100644 --- a/NOTICE +++ b/NOTICE @@ -1,16 +1,16 @@ -Modgud -Copyright (c) 2025 COCOAR e.U. - -Authentication and authorization services for COCOAR applications -Backend API • Frontend UI • OAuth2/OIDC Support - -Licensed under the Apache License, Version 2.0 (the "License"); -You may not use this project except in compliance with the License. -You may obtain a copy at: http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - -Third-Party Notices: -(None at this time) +Modgud +Copyright (c) 2025 COCOAR e.U. + +Authentication and authorization services for COCOAR applications +Backend API • Frontend UI • OAuth2/OIDC Support + +Licensed under the Apache License, Version 2.0 (the "License"); +You may not use this project except in compliance with the License. +You may obtain a copy at: http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +Third-Party Notices: +(None at this time) diff --git a/docs/scripts/export-md.mjs b/docs/scripts/export-md.mjs index d66807b0..88a017d8 100644 --- a/docs/scripts/export-md.mjs +++ b/docs/scripts/export-md.mjs @@ -1,175 +1,175 @@ -#!/usr/bin/env node - -/** - * Exports the VitePress documentation as a single Markdown file. - * - * Usage: node scripts/export-md.mjs [output-path] - * Default: ./dist/modgud-docs.md - */ - -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const ROOT = path.resolve(__dirname, '..'); -const OUTPUT = process.argv[2] || path.join(ROOT, 'dist', 'modgud-docs.md'); - -// ─── Document structure (matches VitePress sidebar) ───────────────────────── - -const structure = [ - { - part: 'Concepts', - pages: [ - { file: 'concepts/glossary.md', title: 'Glossary' }, - { file: 'concepts/realms.md', title: 'Realms' }, - { file: 'concepts/authentication.md', title: 'Authentication Model' }, - { file: 'concepts/oauth.md', title: 'OAuth & OIDC' }, - { file: 'concepts/tokens.md', title: 'Tokens & Sessions' }, - ], - }, - { - part: 'User Guide', - pages: [ - { file: 'user-guide/first-setup.md', title: 'First-Time Setup' }, - { file: 'user-guide/realms.md', title: 'Managing Realms' }, - { file: 'user-guide/realm-setup.md', title: 'Realm Setup Flow' }, - { file: 'user-guide/users.md', title: 'Managing Users' }, - { file: 'user-guide/roles.md', title: 'Managing Roles' }, - { file: 'user-guide/clients.md', title: 'Registering Clients' }, - { file: 'user-guide/scopes.md', title: 'Scopes & Permissions' }, - { file: 'user-guide/api-resources.md', title: 'APIs' }, - { file: 'user-guide/client-flows.md', title: 'Client Flows' }, - { file: 'user-guide/two-factor.md', title: 'Two-Factor Authentication' }, - { file: 'user-guide/sessions.md', title: 'Session Management' }, - ], - }, - { - part: 'Developer Guide', - pages: [ - { file: 'guide/developing-locally.md', title: 'Developing locally' }, - { file: 'guide/architecture.md', title: 'Clean Architecture' }, - { file: 'guide/cqrs-event-sourcing.md', title: 'CQRS & Event Sourcing' }, - { file: 'guide/realms.md', title: 'Multi-Tenancy / Realms' }, - { file: 'guide/auth-cookies.md', title: 'Cookie-Based Auth' }, - { file: 'guide/two-factor.md', title: 'Two-Factor Authentication' }, - { file: 'guide/oauth.md', title: 'OAuth / OpenID Connect' }, - { file: 'guide/frontend.md', title: 'Vue Frontend' }, - { file: 'guide/frontend-realms.md', title: 'Realm-Aware SPA' }, - { file: 'guide/deployment.md', title: 'Docker & Deployment' }, - { file: 'guide/database.md', title: 'Database & Migrations' }, - ], - }, - { - part: 'API Reference', - pages: [ - { file: 'reference/auth-api.md', title: 'Auth Endpoints' }, - { file: 'reference/admin-api.md', title: 'Admin Endpoints' }, - { file: 'reference/realm-api.md', title: 'Realm Endpoints' }, - { file: 'reference/oauth-api.md', title: 'OAuth Endpoints' }, - ], - }, -]; - -// ─── Pre-processing ───────────────────────────────────────────────────────── - -function stripFrontmatter(content) { - return content.replace(/^---[\s\S]*?---\n*/, ''); -} - -function convertContainers(content) { - const lines = content.split('\n'); - const result = []; - const stack = []; - - for (const line of lines) { - const openMatch = line.match(/^::: (\w+)\s*(.*)$/); - if (openMatch) { - const type = openMatch[1]; - const label = openMatch[2]?.trim() || - { tip: 'Tip', warning: 'Warning', info: 'Info', danger: 'Danger', details: 'Details' }[type] || - type.charAt(0).toUpperCase() + type.slice(1); - stack.push(type); - result.push(`> **${label}**`); - result.push('>'); - continue; - } - if (line.trim() === ':::' && stack.length > 0) { - stack.pop(); - result.push(''); - continue; - } - if (stack.length > 0) { - result.push(line ? `> ${line}` : '>'); - } else { - result.push(line); - } - } - - return result.join('\n'); -} - -function processPage(filePath) { - let content = fs.readFileSync(path.join(ROOT, filePath), 'utf-8'); - content = stripFrontmatter(content); - content = convertContainers(content); - return content.trim(); -} - -// ─── Document assembly ────────────────────────────────────────────────────── - -function buildDocument() { - const parts = []; - - // Header - parts.push(`# Modgud Documentation`); - parts.push(''); - parts.push(`*Multi-tenant Identity Provider — ${new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long' })}*`); - parts.push(''); - parts.push('---'); - parts.push(''); - - // Table of contents - parts.push('## Table of Contents'); - parts.push(''); - for (const section of structure) { - parts.push(`**${section.part}**`); - for (const page of section.pages) { - parts.push(`- ${page.title}`); - } - parts.push(''); - } - parts.push('---'); - parts.push(''); - - // Content - for (const section of structure) { - parts.push(`# ${section.part}`); - parts.push(''); - - for (const page of section.pages) { - const content = processPage(page.file); - parts.push(content); - parts.push(''); - parts.push('---'); - parts.push(''); - } - } - - return parts.join('\n'); -} - -// ─── Main ─────────────────────────────────────────────────────────────────── - -const pageCount = structure.reduce((sum, s) => sum + s.pages.length, 0); -console.log(`Exporting Modgud documentation to Markdown...\n`); -console.log(` Sections: ${structure.length}`); -console.log(` Pages: ${pageCount}`); - -const doc = buildDocument(); - -fs.mkdirSync(path.dirname(OUTPUT), { recursive: true }); -fs.writeFileSync(OUTPUT, doc, 'utf-8'); - -const sizeKb = (Buffer.byteLength(doc, 'utf-8') / 1024).toFixed(0); -console.log(`\n Output: ${OUTPUT} (${sizeKb} KB)\n`); +#!/usr/bin/env node + +/** + * Exports the VitePress documentation as a single Markdown file. + * + * Usage: node scripts/export-md.mjs [output-path] + * Default: ./dist/modgud-docs.md + */ + +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const ROOT = path.resolve(__dirname, '..'); +const OUTPUT = process.argv[2] || path.join(ROOT, 'dist', 'modgud-docs.md'); + +// ─── Document structure (matches VitePress sidebar) ───────────────────────── + +const structure = [ + { + part: 'Concepts', + pages: [ + { file: 'concepts/glossary.md', title: 'Glossary' }, + { file: 'concepts/realms.md', title: 'Realms' }, + { file: 'concepts/authentication.md', title: 'Authentication Model' }, + { file: 'concepts/oauth.md', title: 'OAuth & OIDC' }, + { file: 'concepts/tokens.md', title: 'Tokens & Sessions' }, + ], + }, + { + part: 'User Guide', + pages: [ + { file: 'user-guide/first-setup.md', title: 'First-Time Setup' }, + { file: 'user-guide/realms.md', title: 'Managing Realms' }, + { file: 'user-guide/realm-setup.md', title: 'Realm Setup Flow' }, + { file: 'user-guide/users.md', title: 'Managing Users' }, + { file: 'user-guide/roles.md', title: 'Managing Roles' }, + { file: 'user-guide/clients.md', title: 'Registering Clients' }, + { file: 'user-guide/scopes.md', title: 'Scopes & Permissions' }, + { file: 'user-guide/api-resources.md', title: 'APIs' }, + { file: 'user-guide/client-flows.md', title: 'Client Flows' }, + { file: 'user-guide/two-factor.md', title: 'Two-Factor Authentication' }, + { file: 'user-guide/sessions.md', title: 'Session Management' }, + ], + }, + { + part: 'Developer Guide', + pages: [ + { file: 'guide/developing-locally.md', title: 'Developing locally' }, + { file: 'guide/architecture.md', title: 'Clean Architecture' }, + { file: 'guide/cqrs-event-sourcing.md', title: 'CQRS & Event Sourcing' }, + { file: 'guide/realms.md', title: 'Multi-Tenancy / Realms' }, + { file: 'guide/auth-cookies.md', title: 'Cookie-Based Auth' }, + { file: 'guide/two-factor.md', title: 'Two-Factor Authentication' }, + { file: 'guide/oauth.md', title: 'OAuth / OpenID Connect' }, + { file: 'guide/frontend.md', title: 'Vue Frontend' }, + { file: 'guide/frontend-realms.md', title: 'Realm-Aware SPA' }, + { file: 'guide/deployment.md', title: 'Docker & Deployment' }, + { file: 'guide/database.md', title: 'Database & Migrations' }, + ], + }, + { + part: 'API Reference', + pages: [ + { file: 'reference/auth-api.md', title: 'Auth Endpoints' }, + { file: 'reference/admin-api.md', title: 'Admin Endpoints' }, + { file: 'reference/realm-api.md', title: 'Realm Endpoints' }, + { file: 'reference/oauth-api.md', title: 'OAuth Endpoints' }, + ], + }, +]; + +// ─── Pre-processing ───────────────────────────────────────────────────────── + +function stripFrontmatter(content) { + return content.replace(/^---[\s\S]*?---\n*/, ''); +} + +function convertContainers(content) { + const lines = content.split('\n'); + const result = []; + const stack = []; + + for (const line of lines) { + const openMatch = line.match(/^::: (\w+)\s*(.*)$/); + if (openMatch) { + const type = openMatch[1]; + const label = openMatch[2]?.trim() || + { tip: 'Tip', warning: 'Warning', info: 'Info', danger: 'Danger', details: 'Details' }[type] || + type.charAt(0).toUpperCase() + type.slice(1); + stack.push(type); + result.push(`> **${label}**`); + result.push('>'); + continue; + } + if (line.trim() === ':::' && stack.length > 0) { + stack.pop(); + result.push(''); + continue; + } + if (stack.length > 0) { + result.push(line ? `> ${line}` : '>'); + } else { + result.push(line); + } + } + + return result.join('\n'); +} + +function processPage(filePath) { + let content = fs.readFileSync(path.join(ROOT, filePath), 'utf-8'); + content = stripFrontmatter(content); + content = convertContainers(content); + return content.trim(); +} + +// ─── Document assembly ────────────────────────────────────────────────────── + +function buildDocument() { + const parts = []; + + // Header + parts.push(`# Modgud Documentation`); + parts.push(''); + parts.push(`*Multi-tenant Identity Provider — ${new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long' })}*`); + parts.push(''); + parts.push('---'); + parts.push(''); + + // Table of contents + parts.push('## Table of Contents'); + parts.push(''); + for (const section of structure) { + parts.push(`**${section.part}**`); + for (const page of section.pages) { + parts.push(`- ${page.title}`); + } + parts.push(''); + } + parts.push('---'); + parts.push(''); + + // Content + for (const section of structure) { + parts.push(`# ${section.part}`); + parts.push(''); + + for (const page of section.pages) { + const content = processPage(page.file); + parts.push(content); + parts.push(''); + parts.push('---'); + parts.push(''); + } + } + + return parts.join('\n'); +} + +// ─── Main ─────────────────────────────────────────────────────────────────── + +const pageCount = structure.reduce((sum, s) => sum + s.pages.length, 0); +console.log(`Exporting Modgud documentation to Markdown...\n`); +console.log(` Sections: ${structure.length}`); +console.log(` Pages: ${pageCount}`); + +const doc = buildDocument(); + +fs.mkdirSync(path.dirname(OUTPUT), { recursive: true }); +fs.writeFileSync(OUTPUT, doc, 'utf-8'); + +const sizeKb = (Buffer.byteLength(doc, 'utf-8') / 1024).toFixed(0); +console.log(`\n Output: ${OUTPUT} (${sizeKb} KB)\n`); diff --git a/docs/scripts/export-pdf.mjs b/docs/scripts/export-pdf.mjs index 751e5e7e..bb0df6e9 100644 --- a/docs/scripts/export-pdf.mjs +++ b/docs/scripts/export-pdf.mjs @@ -1,349 +1,349 @@ -#!/usr/bin/env node - -/** - * Exports the VitePress documentation as a single, professionally-formatted PDF. - * - * Usage: node scripts/export-pdf.mjs [output-path] - * Default: ./dist/modgud-docs.pdf - */ - -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import MarkdownIt from 'markdown-it'; -import hljs from 'highlight.js'; -import puppeteer from 'puppeteer-core'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const ROOT = path.resolve(__dirname, '..'); -const OUTPUT = process.argv[2] || path.join(ROOT, 'dist', 'modgud-docs.pdf'); - -// ─── Document structure (matches VitePress sidebar) ───────────────────────── - -const structure = [ - { - part: 'Concepts', - pages: [ - { file: 'concepts/glossary.md', title: 'Glossary' }, - { file: 'concepts/realms.md', title: 'Realms' }, - { file: 'concepts/authentication.md', title: 'Authentication Model' }, - { file: 'concepts/oauth.md', title: 'OAuth & OIDC' }, - { file: 'concepts/tokens.md', title: 'Tokens & Sessions' }, - ], - }, - { - part: 'User Guide', - pages: [ - { file: 'user-guide/first-setup.md', title: 'First-Time Setup' }, - { file: 'user-guide/realms.md', title: 'Managing Realms' }, - { file: 'user-guide/realm-setup.md', title: 'Realm Setup Flow' }, - { file: 'user-guide/users.md', title: 'Managing Users' }, - { file: 'user-guide/roles.md', title: 'Managing Roles' }, - { file: 'user-guide/clients.md', title: 'Registering Clients' }, - { file: 'user-guide/scopes.md', title: 'Scopes & Permissions' }, - { file: 'user-guide/api-resources.md', title: 'APIs' }, - { file: 'user-guide/client-flows.md', title: 'Client Flows' }, - { file: 'user-guide/two-factor.md', title: 'Two-Factor Authentication' }, - { file: 'user-guide/sessions.md', title: 'Session Management' }, - ], - }, - { - part: 'Developer Guide', - pages: [ - { file: 'guide/developing-locally.md', title: 'Developing locally' }, - { file: 'guide/architecture.md', title: 'Clean Architecture' }, - { file: 'guide/cqrs-event-sourcing.md', title: 'CQRS & Event Sourcing' }, - { file: 'guide/realms.md', title: 'Multi-Tenancy / Realms' }, - { file: 'guide/auth-cookies.md', title: 'Cookie-Based Auth' }, - { file: 'guide/two-factor.md', title: 'Two-Factor Authentication' }, - { file: 'guide/oauth.md', title: 'OAuth / OpenID Connect' }, - { file: 'guide/frontend.md', title: 'Vue Frontend' }, - { file: 'guide/frontend-realms.md', title: 'Realm-Aware SPA' }, - { file: 'guide/deployment.md', title: 'Docker & Deployment' }, - { file: 'guide/database.md', title: 'Database & Migrations' }, - ], - }, - { - part: 'API Reference', - pages: [ - { file: 'reference/auth-api.md', title: 'Auth Endpoints' }, - { file: 'reference/admin-api.md', title: 'Admin Endpoints' }, - { file: 'reference/realm-api.md', title: 'Realm Endpoints' }, - { file: 'reference/oauth-api.md', title: 'OAuth Endpoints' }, - ], - }, -]; - -// ─── Markdown setup ───────────────────────────────────────────────────────── - -const md = new MarkdownIt({ - html: true, - linkify: true, - typographer: true, - highlight(str, lang) { - if (lang && hljs.getLanguage(lang)) { - try { - return `
${hljs.highlight(str, { language: lang }).value}`;
- } catch (_) { /* fall through */ }
- }
- return `${md.utils.escapeHtml(str)}`;
- },
-});
-
-// ─── Markdown pre-processing ────────────────────────────────────────────────
-
-function slugify(text) {
- return text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
-}
-
-function stripFrontmatter(content) {
- return content.replace(/^---[\s\S]*?---\n*/, '');
-}
-
-function convertContainers(content) {
- const lines = content.split('\n');
- const result = [];
- const stack = [];
-
- for (const line of lines) {
- const openMatch = line.match(/^::: (\w+)\s*(.*)$/);
- if (openMatch) {
- const type = openMatch[1];
- const title = openMatch[2]?.trim() ||
- { tip: 'Tip', warning: 'Warning', info: 'Info', danger: 'Danger', details: 'Details' }[type] ||
- type.charAt(0).toUpperCase() + type.slice(1);
- stack.push(type);
- result.push(`${title}
`); - result.push(''); - continue; - } - if (line.trim() === ':::' && stack.length > 0) { - stack.pop(); - result.push(''); - result.push('Multi-tenant Identity Provider
- -${hljs.highlight(str, { language: lang }).value}`;
+ } catch (_) { /* fall through */ }
+ }
+ return `${md.utils.escapeHtml(str)}`;
+ },
+});
+
+// ─── Markdown pre-processing ────────────────────────────────────────────────
+
+function slugify(text) {
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
+}
+
+function stripFrontmatter(content) {
+ return content.replace(/^---[\s\S]*?---\n*/, '');
+}
+
+function convertContainers(content) {
+ const lines = content.split('\n');
+ const result = [];
+ const stack = [];
+
+ for (const line of lines) {
+ const openMatch = line.match(/^::: (\w+)\s*(.*)$/);
+ if (openMatch) {
+ const type = openMatch[1];
+ const title = openMatch[2]?.trim() ||
+ { tip: 'Tip', warning: 'Warning', info: 'Info', danger: 'Danger', details: 'Details' }[type] ||
+ type.charAt(0).toUpperCase() + type.slice(1);
+ stack.push(type);
+ result.push(`${title}
`); + result.push(''); + continue; + } + if (line.trim() === ':::' && stack.length > 0) { + stack.pop(); + result.push(''); + result.push('Multi-tenant Identity Provider
+ +