Compare commits

..

2 Commits

Author SHA1 Message Date
dependabot[bot] 6b231c2958 chore(deps): bump modernc.org/sqlite
Bumps the minor-patch group with 1 update in the / directory: [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).


Updates `modernc.org/sqlite` from 1.49.1 to 1.50.0
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.49.1...v1.50.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-version: 1.50.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-28 08:25:02 +00:00
Stavros c68a022ed0 docs: add ai policy (#821)
* docs: add ai policy

* docs: rework ai policy for more clear rules and expectations

* chore: review comments

* chore: rabbit feedback

* chore: update contributing guide to reference ai policy
2026-04-27 20:44:44 +03:00
11 changed files with 47 additions and 79 deletions
+27
View File
@@ -0,0 +1,27 @@
# AI Usage Policy
> [!NOTE]
> By Tinyauth, we refer to the entire Tinyauth ([tinyauthapp](https://github.com/tinyauthapp)) organization and all of the repositories under it.
## How we utilize AI in Tinyauth
In Tinyauth, we see AI as another tool designed to help developers accelerate their work, ***not*** as something that should be doing the development for them. The ways we utilize large language models in Tinyauth are the following:
- **Pull request reviews**: We utilize [CodeRabbit](https://www.coderabbit.ai/) for reviews in our pull requests which helps us find and fix issues faster, minimizing the time maintainers have to spend reviewing.
- **Documentation and Issues**: We use [Dosu](https://dosu.dev/) to help resolve duplicate issues faster and automatically update our documentation based on changes in the code base.
- **In-Line Suggestions**: GitHub's [Copilot](https://github.com/features/copilot) is partially used to fill in boilerplate code through in-line suggestions.
## How we expect the community to use AI
We expect the Tinyauth community to use AI as a tool for faster development and not as a way to implement entire features through prompts. For this reason, the following guidelines are in place for AI generated content:
- **All usage must be clearly labeled**: Any content generated by AI must be clearly labeled as such. In the case that a pull request is clearly generated by AI and the author fails to disclose its use, it will be rejected.
- **All generated content should be completely understood by the account holder**: The human who utilized the large language model to generate content must have a thorough understanding of it. This includes understanding the resulting output to the full extent and being able to explain it in detail in case it's needed.
- **Automated systems are not allowed**: All forms of automated systems that utilize large language models to generate content without human oversight are forbidden. This includes any system that generates content without a human being directly involved in the process like for example with OpenClaw.
- **No generated content other than text is allowed**: Images, videos, audio and any other form of content generated by AI other than text is not allowed in Tinyauth.
- **AI pull requests are not guaranteed to be accepted or prioritized**: Any pull request that contains AI generated content is not guaranteed to be accepted and/or prioritized. The maintainers are responsible for reviewing all pull requests and determining whether or not they meet the standards of the project. AI generated content will be reviewed with the same standards as any other content, and may be rejected if it does not meet those standards.
- **Large generated pull requests will be rejected**: Any pull request that contains a large amount of generated content will be rejected. This is because it is difficult for the maintainers to review and verify large amounts of generated content.
## Tinyauth is developed by humans, for humans
Please remember that Tinyauth is developed by humans. While AI can be a useful tool for **assisting** in the development process, it should not be used in place of the human brain. Moving forward, we are committed to ensuring that most, if not all the content in Tinyauth is created and reviewed by humans, and that AI is only used as a tool to assist in the development process.
+3
View File
@@ -2,6 +2,9 @@
Contributing to Tinyauth is straightforward. Follow the steps below to set up a development server.
> [!NOTE]
> If you are using large language models to contribute to the project, please ensure that you have read and understood the [AI Policy](AI_POLICY.md).
## Requirements
- Bun
+1 -1
View File
@@ -6,4 +6,4 @@ It is recommended to use the [latest](https://github.com/tinyauthapp/tinyauth/re
## Reporting a Vulnerability
Due to the nature of this app, it needs to be secure. If you discover any security issues or vulnerabilities in the app please contact me as soon as possible at <steve@doesmycode.work>. Please do not use the issues section to report security issues as I won't be able to patch them in time and they may get exploited by malicious actors.
Due to the nature of this app, it needs to be secure. If you discover any security issues or vulnerabilities in the app please contact me as soon as possible at <security@tinyauth.app>. Please do not use the issues section to report security issues as I won't be able to patch them in time and they may get exploited by malicious actors.
-10
View File
@@ -57,16 +57,6 @@ export default defineConfig({
changeOrigin: true,
rewrite: (path) => path.replace(/^\/robots.txt/, ""),
},
"/authorize": {
target: "http://tinyauth-backend:3000/authorize",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/authorize/, ""),
bypass: (req) => {
if (req.method === "GET") {
return "/index.html";
}
},
},
},
allowedHosts: true,
},
+1 -1
View File
@@ -22,7 +22,7 @@ require (
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546
golang.org/x/oauth2 v0.36.0
gotest.tools/v3 v3.5.2
modernc.org/sqlite v1.49.1
modernc.org/sqlite v1.50.0
)
require (
+2 -2
View File
@@ -351,8 +351,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
modernc.org/sqlite v1.49.1 h1:dYGHTKcX1sJ+EQDnUzvz4TJ5GbuvhNJa8Fg6ElGx73U=
modernc.org/sqlite v1.49.1/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew=
modernc.org/sqlite v1.50.0 h1:eMowQSWLK0MeiQTdmz3lqoF5dqclujdlIKeJA11+7oM=
modernc.org/sqlite v1.50.0/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew=
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
+1 -1
View File
@@ -87,7 +87,7 @@ func (app *BootstrapApp) setupRouter() (*gin.Engine, error) {
oauthController.SetupRoutes()
oidcController := controller.NewOIDCController(controller.OIDCControllerConfig{}, app.services.oidcService, apiRouter, engine)
oidcController := controller.NewOIDCController(controller.OIDCControllerConfig{}, app.services.oidcService, apiRouter)
oidcController.SetupRoutes()
+1 -17
View File
@@ -3,7 +3,6 @@ package controller
import (
"errors"
"fmt"
"io"
"net/http"
"slices"
"strings"
@@ -22,7 +21,6 @@ type OIDCController struct {
config OIDCControllerConfig
router *gin.RouterGroup
oidc *service.OIDCService
engine *gin.Engine
}
type AuthorizeCallback struct {
@@ -59,12 +57,11 @@ type ClientCredentials struct {
ClientSecret string
}
func NewOIDCController(config OIDCControllerConfig, oidcService *service.OIDCService, router *gin.RouterGroup, engine *gin.Engine) *OIDCController {
func NewOIDCController(config OIDCControllerConfig, oidcService *service.OIDCService, router *gin.RouterGroup) *OIDCController {
return &OIDCController{
config: config,
oidc: oidcService,
router: router,
engine: engine,
}
}
@@ -75,7 +72,6 @@ func (controller *OIDCController) SetupRoutes() {
oidcGroup.POST("/token", controller.Token)
oidcGroup.GET("/userinfo", controller.Userinfo)
oidcGroup.POST("/userinfo", controller.Userinfo)
controller.engine.POST("/authorize", controller.AuthorizePseudoPost)
}
func (controller *OIDCController) GetClientInfo(c *gin.Context) {
@@ -199,18 +195,6 @@ func (controller *OIDCController) Authorize(c *gin.Context) {
})
}
// Pseudo handler that will just redirect to get in frontend then back to backend
func (controller *OIDCController) AuthorizePseudoPost(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
tlog.App.Error().Err(err).Msg("Failed to read request body")
c.Redirect(http.StatusFound, fmt.Sprintf("%s/authorize", controller.oidc.GetIssuer()))
return
}
redirectUrl := fmt.Sprintf("%s/authorize?%s", controller.oidc.GetIssuer(), body)
c.Redirect(http.StatusFound, redirectUrl)
}
func (controller *OIDCController) Token(c *gin.Context) {
if !controller.oidc.IsConfigured() {
tlog.App.Warn().Msg("OIDC not configured")
+3 -31
View File
@@ -12,14 +12,14 @@ import (
"github.com/gin-gonic/gin"
"github.com/google/go-querystring/query"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tinyauthapp/tinyauth/internal/bootstrap"
"github.com/tinyauthapp/tinyauth/internal/config"
"github.com/tinyauthapp/tinyauth/internal/controller"
"github.com/tinyauthapp/tinyauth/internal/repository"
"github.com/tinyauthapp/tinyauth/internal/service"
"github.com/tinyauthapp/tinyauth/internal/utils/tlog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestOIDCController(t *testing.T) {
@@ -846,34 +846,6 @@ func TestOIDCController(t *testing.T) {
assert.Equal(t, "invalid_grant", res["error"])
},
},
{
description: "Test authorize request with POST method",
middlewares: []gin.HandlerFunc{
simpleCtx,
},
run: func(t *testing.T, router *gin.Engine, recorder *httptest.ResponseRecorder) {
body := service.AuthorizeRequest{
Scope: "openid",
ResponseType: "code",
ClientID: "some-client-id",
RedirectURI: "https://test.example.com/callback",
State: "some-state",
Nonce: "some-nonce",
CodeChallenge: "some-challenge",
CodeChallengeMethod: "plain",
}
queries, err := query.Values(body)
assert.NoError(t, err)
req := httptest.NewRequest("POST", "/authorize", strings.NewReader(string(queries.Encode())))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
router.ServeHTTP(recorder, req)
assert.Equal(t, 302, recorder.Code)
location := recorder.Header().Get("Location")
assert.NotEmpty(t, location)
assert.Equal(t, "https://tinyauth.example.com/authorize?client_id=some-client-id&code_challenge=some-challenge&code_challenge_method=plain&nonce=some-nonce&redirect_uri=https%3A%2F%2Ftest.example.com%2Fcallback&response_type=code&scope=openid&state=some-state", location)
},
},
}
app := bootstrap.NewBootstrapApp(config.Config{})
@@ -897,7 +869,7 @@ func TestOIDCController(t *testing.T) {
group := router.Group("/api")
gin.SetMode(gin.TestMode)
oidcController := controller.NewOIDCController(controllerCfg, oidcService, group, router)
oidcController := controller.NewOIDCController(controllerCfg, oidcService, group)
oidcController.SetupRoutes()
recorder := httptest.NewRecorder()
-7
View File
@@ -39,7 +39,6 @@ func (m *UIMiddleware) Init() error {
func (m *UIMiddleware) Middleware() gin.HandlerFunc {
return func(c *gin.Context) {
path := strings.TrimPrefix(c.Request.URL.Path, "/")
method := c.Request.Method
tlog.App.Debug().Str("path", path).Msg("path")
@@ -53,12 +52,6 @@ func (m *UIMiddleware) Middleware() gin.HandlerFunc {
c.Writer.Write([]byte("User-agent: *\nDisallow: /\n"))
return
default:
// For OIDC post authentication, we need to redirect the POST to /authorize to the backend
if method == http.MethodPost && strings.HasPrefix(path, "authorize") {
c.Next()
return
}
_, err := fs.Stat(m.uiFs, path)
// Enough for one authentication flow
+8 -9
View File
@@ -100,15 +100,14 @@ type TokenResponse struct {
}
type AuthorizeRequest struct {
Scope string `json:"scope" binding:"required" url:"scope"`
ResponseType string `json:"response_type" binding:"required" url:"response_type"`
ClientID string `json:"client_id" binding:"required" url:"client_id"`
RedirectURI string `json:"redirect_uri" binding:"required" url:"redirect_uri"`
State string `json:"state" url:"state"`
Nonce string `json:"nonce" url:"nonce"`
CodeChallenge string `json:"code_challenge" url:"code_challenge"`
CodeChallengeMethod string `json:"code_challenge_method" url:"code_challenge_method"`
Request string `json:"request" url:"request"`
Scope string `json:"scope" binding:"required"`
ResponseType string `json:"response_type" binding:"required"`
ClientID string `json:"client_id" binding:"required"`
RedirectURI string `json:"redirect_uri" binding:"required"`
State string `json:"state"`
Nonce string `json:"nonce"`
CodeChallenge string `json:"code_challenge"`
CodeChallengeMethod string `json:"code_challenge_method"`
}
type OIDCServiceConfig struct {