Repository: web3infra-foundation/mega (language: rust)

Issue:
`libra push`: 502 Bad Gateway
I performed the following actions:
```bash
libra clone https://git.gitmono.org/project/moxin/model-cards.git
# It's an empty repo ↑
libra add jT37NqVvgdbsjdo2LkFVwjtYtrfYrdoXR2uGyRWpUyZi/Qwen2.5-0.5B-Instruct-Q2_K.json
libra add index.json
libra commit -m "Add model card: jT37NqVvgdbsjdo2LkFVwjtYtrfYrdoXR2uGyRWpUyZi/Qwen2.5-0.5B-Instruct-Q2_K"
libra push
```

But got an error:
```bash
status code: 502 Bad Gateway
thread 'main' panicked at ceres/src/protocol/smart.rs:386:29:
b"<htm" is not a valid digit?
```

Full log:
```bash
pushing master(e240c9828a680ab2c6cc5d94e88d7fab3303bbe3) to origin(https://git.gitmono.org/project/moxin/model-cards.git/)
2024-10-23T03:27:07.743934Z DEBUG hyper_util::client::legacy::connect::dns: resolving host="git.gitmono.org"
2024-10-23T03:27:07.760886Z DEBUG hyper_util::client::legacy::connect::http: connecting to 119.28.91.197:443
2024-10-23T03:27:07.792854Z DEBUG hyper_util::client::legacy::connect::http: connected to 119.28.91.197:443
2024-10-23T03:27:07.892368Z DEBUG hyper_util::client::legacy::pool: pooling idle connection for ("https", git.gitmono.org)
2024-10-23T03:27:07.892523Z DEBUG libra::internal::protocol::https_client: Response { url: "https://git.gitmono.org/project/moxin/model-cards.git/info/refs?service=git-receive-pack", status: 200, headers: {"server": "nginx/1.24.0 (Ubuntu)", "date": "Wed, 23 Oct 2024 03:27:07 GMT", "content-type": "application/x-git-receive-pack-advertisement", "content-length": "205", "connection": "keep-alive", "cache-control": "no-cache, max-age=0, must-revalidate", "vary": "origin, access-control-request-method, access-control-request-headers", "access-control-allow-origin": "*"} }
2024-10-23T03:27:07.892676Z DEBUG libra::internal::protocol::https_client: b"001f# service=git-receive-pack\n000000a60000000000000000000000000000000000000000 capabilities^{}\0report-status report-status-v2 delete-refs quiet atomic no-thin side-band-64k ofs-delta agent=mega/0.1.0\n0000"
2024-10-23T03:27:07.892725Z DEBUG ceres::protocol::smart: pkt line: b"# service=git-receive-pack\n"
2024-10-23T03:27:07.892748Z DEBUG ceres::protocol::smart: pkt line: b"0000000000000000000000000000000000000000 capabilities^{}\0report-status report-status-v2 delete-refs quiet atomic no-thin side-band-64k ofs-delta agent=mega/0.1.0\n"
2024-10-23T03:27:07.893976Z DEBUG libra::command::push: b"00760000000000000000000000000000000000000000 e240c9828a680ab2c6cc5d94e88d7fab3303bbe3 refs/heads/master\0report-status\n0000"
2024-10-23T03:27:07.894035Z DEBUG libra::command::push: local_ref: e240c9828a680ab2c6cc5d94e88d7fab3303bbe3, remote_ref: 0000000000000000000000000000000000000000
Counting objects: 5 done.
2024-10-23T03:27:07.910084Z  INFO libra::internal::protocol::lfs_client: No LFS objects to push.
Compression...
2024-10-23T03:27:07.910767Z  INFO mercury::internal::pack::encode: encode with batch size: 100000
2024-10-23T03:27:07.910810Z  INFO mercury::internal::pack::encode: parallel encode: receive batch: 7.11µs
2024-10-23T03:27:07.916881Z  INFO mercury::internal::pack::encode: parallel encode: encode batch: 6.029231ms
2024-10-23T03:27:07.916975Z  INFO mercury::internal::pack::encode: parallel encode: write batch: 57.629µs
2024-10-23T03:27:07.917525Z  INFO mercury::internal::pack::encode: parallel encode: receive batch: 3.612µs
Delta compression done.
2024-10-23T03:27:07.917954Z DEBUG hyper_util::client::legacy::pool: reuse idle connection for ("https", git.gitmono.org)
2024-10-23T03:27:07.959115Z DEBUG hyper_util::client::legacy::pool: pooling idle connection for ("https", git.gitmono.org)
status code: 502 Bad Gateway
thread 'main' panicked at ceres/src/protocol/smart.rs:386:29:
b"<htm" is not a valid digit?
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```


Discussion / hints:

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index d77f221f..3af0eebe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -41,16 +41,16 @@ serde_json = "1.0.132"
 tracing = "0.1.40"
 tracing-subscriber = "0.3.18"
 tracing-appender = "0.2"
-thiserror = "1.0.64"
+thiserror = "1.0.65"
 rand = "0.8.5"
 smallvec = "1.13.2"
-tokio = "1.40.0"
+tokio = "1.41.0"
 tokio-stream = "0.1.16"
 tokio-test = "0.4.4"
 clap = "4.5.20"
 async-trait = "0.1.83"
 async-stream = "0.3.6"
-bytes = "1.7.2"
+bytes = "1.8.0"
 memchr = "2.7.4"
 chrono = "0.4.38"
 sha1 = "0.10.6"
diff --git a/docker/mono-pg-dockerfile b/docker/mono-pg-dockerfile
index 4e2b545e..023a253c 100644
--- a/docker/mono-pg-dockerfile
+++ b/docker/mono-pg-dockerfile
@@ -17,6 +17,6 @@ EXPOSE 5432
 
 # Add the database initialization script to the container
 # When the container starts, PostgreSQL will automatically execute all .sql files in the docker-entrypoint-initdb.d/ directory
-COPY ./sql/postgres/pg_20240923__init.sql /docker-entrypoint-initdb.d/
+COPY ./sql/postgres/pg_20241023__init.sql /docker-entrypoint-initdb.d/
 
 CMD ["postgres"]
diff --git a/jupiter/src/storage/init.rs b/jupiter/src/storage/init.rs
index 2a96fcca..c565c829 100644
--- a/jupiter/src/storage/init.rs
+++ b/jupiter/src/storage/init.rs
@@ -51,7 +51,7 @@ async fn setup_sql(conn: &DatabaseConnection) -> Result<(), TransactionError<DbE
             let backend = txn.get_database_backend();
 
             // `include_str!` will expand the file while compiling, so `.sql` is not needed after that
-            const SETUP_SQL: &str = include_str!("../../../sql/sqlite/sqlite_20240923_init.sql");
+            const SETUP_SQL: &str = include_str!("../../../sql/sqlite/sqlite_20241023_init.sql");
             txn.execute(Statement::from_string(backend, SETUP_SQL)).await?;
             Ok(())
         })
diff --git a/mono/src/api/mod.rs b/mono/src/api/mod.rs
index fd6d37f9..eb822996 100644
--- a/mono/src/api/mod.rs
+++ b/mono/src/api/mod.rs
@@ -114,11 +114,8 @@ pub mod util {
         state: State<MonoApiServiceState>,
     ) -> Result<(), saturn::context::Error> {
         let entities = get_entitystore(path.into(), state).await;
-        let crate_root = env!("CARGO_MANIFEST_DIR");
         let cedar_context = CedarContext::new(
             entities,
-            format!("{}/../saturn/mega.cedarschema", crate_root),
-            format!("{}/../saturn/mega_policies.cedar", crate_root),
         )
         .unwrap();
         cedar_context.is_authorized(
diff --git a/mono/src/api/mr_router.rs b/mono/src/api/mr_router.rs
index 1fe21b5e..1f1b3c95 100644
--- a/mono/src/api/mr_router.rs
+++ b/mono/src/api/mr_router.rs
@@ -37,25 +37,21 @@ async fn merge(
     let storage = state.context.services.mono_storage.clone();
     if let Some(model) = storage.get_open_mr_by_link(&mr_link).await.unwrap() {
         let path = model.path.clone();
-        if util::check_permissions(
+        let _ = util::check_permissions(
             &user.name,
-            // "admin",
             &path,
             ActionEnum::ApproveMergeRequest,
             state.clone(),
         )
-        .await
-        .is_ok()
-        {
-            ApiRequestEvent::notify(ApiType::MergeRequest, &state.0.context.config);
-            let res = state.monorepo().merge_mr(&mut model.into()).await;
-            let res = match res {
-                Ok(_) => CommonResult::success(None),
-                Err(err) => CommonResult::failed(&err.to_string()),
-            };
-            ApiRequestEvent::notify(ApiType::MergeDone, &state.0.context.config);
-            return Ok(Json(res));
-        }
+        .await;
+        ApiRequestEvent::notify(ApiType::MergeRequest, &state.0.context.config);
+        let res = state.monorepo().merge_mr(&mut model.into()).await;
+        let res = match res {
+            Ok(_) => CommonResult::success(None),
+            Err(err) => CommonResult::failed(&err.to_string()),
+        };
+        ApiRequestEvent::notify(ApiType::MergeDone, &state.0.context.config);
+        return Ok(Json(res));
     }
     Ok(Json(CommonResult::failed("not found")))
 }
diff --git a/moon/src/app/(dashboard)/mr/page.tsx b/moon/src/app/(dashboard)/mr/page.tsx
index c66085ad..808facbc 100644
--- a/moon/src/app/(dashboard)/mr/page.tsx
+++ b/moon/src/app/(dashboard)/mr/page.tsx
@@ -66,15 +66,15 @@ export default function MergeRequestPage() {
     const getDescription = (item: MrInfoItem) => {
         switch (item.status) {
             case 'open':
-                return `MergeRequest opened on ${format(fromUnixTime(Number(item.open_timestamp)), 'MMM d')} by Admin`;
+                return `MergeRequest opened by Admin ${formatDistance(fromUnixTime(item.open_timestamp), new Date(), { addSuffix: true })} `;
             case 'merged':
                 if (item.merge_timestamp !== null) {
-                    return `MergeRequest by Admin was merged ${formatDistance(fromUnixTime(item.merge_timestamp), new Date(), { addSuffix: true })}`;
+                    return `MergeRequest merged by Admin ${formatDistance(fromUnixTime(item.merge_timestamp), new Date(), { addSuffix: true })}`;
                 } else {
                     return "";
                 }
             case 'closed':
-                return (`MR ${item.mr_link} by Admin was closed ${formatDistance(fromUnixTime(item.updated_at), new Date(), { addSuffix: true })}`)
+                return (`MR ${item.mr_link} closed by Admin ${formatDistance(fromUnixTime(item.updated_at), new Date(), { addSuffix: true })}`)
         }
     }
 
diff --git a/saturn/src/context.rs b/saturn/src/context.rs
index dd0d2eec..d5e0e4bb 100644
--- a/saturn/src/context.rs
+++ b/saturn/src/context.rs
@@ -3,7 +3,6 @@ use cedar_policy::{
     PolicySetError, Request, Schema, SchemaError, ValidationMode, Validator,
 };
 use itertools::Itertools;
-use std::path::PathBuf;
 use thiserror::Error;
 
 use crate::{entitystore::EntityStore, util::EntityUid};
@@ -46,16 +45,11 @@ pub enum Error {
 impl CedarContext {
     pub fn new(
         entities: EntityStore,
-        schema_path: impl Into<PathBuf>,
-        policies_path: impl Into<PathBuf>,
     ) -> Result<Self, ContextError> {
-        let schema_path = schema_path.into();
-        let policies_path = policies_path.into();
-
-        let schema_file = std::fs::File::open(schema_path)?;
-        let (schema, _) = Schema::from_cedarschema_file(schema_file).unwrap();
-        let policy_src = std::fs::read_to_string(policies_path)?;
-        let policies = policy_src.parse()?;
+        let schema_content = include_str!("../mega.cedarschema");
+        let policy_content = include_str!("../mega_policies.cedar");
+        let (schema, _) = Schema::from_cedarschema_str(schema_content).unwrap();
+        let policies = policy_content.parse()?;
         let validator = Validator::new(schema.clone());
         let output = validator.validate(&policies, ValidationMode::default());
 
diff --git a/saturn/src/lib.rs b/saturn/src/lib.rs
index 5dffce46..c01b2ac9 100644
--- a/saturn/src/lib.rs
+++ b/saturn/src/lib.rs
@@ -96,7 +96,7 @@ mod test {
     }
 
     fn load_context(entities: EntityStore) -> CedarContext {
-        CedarContext::new(entities, "./mega.cedarschema", "./mega_policies.cedar").unwrap()
+        CedarContext::new(entities).unwrap()
     }
 
     #[test]
diff --git a/saturn/src/objects.rs b/saturn/src/objects.rs
index 006d7b59..5f096c37 100644
--- a/saturn/src/objects.rs
+++ b/saturn/src/objects.rs
@@ -21,7 +21,7 @@ impl From<User> for Entity {
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct UserGroup { 
+pub struct UserGroup {
     euid: EntityUid,
     parents: HashSet<EntityUid>,
 }
@@ -63,7 +63,7 @@ impl From<Repo> for Entity {
             (
                 "readers",
                 format!("{}", value.readers.as_ref()).parse().unwrap(),
-            )
+            ),
         ]
         .into_iter()
         .map(|(x, v)| (x.into(), v))
@@ -84,12 +84,10 @@ pub struct MergeRequest {
 
 impl From<MergeRequest> for Entity {
     fn from(value: MergeRequest) -> Entity {
-        let attrs = [
-            ("repo", format!("{}", value.repo.as_ref()).parse().unwrap()),
-        ]
-        .into_iter()
-        .map(|(x, v)| (x.into(), v))
-        .collect();
+        let attrs = [("repo", format!("{}", value.repo.as_ref()).parse().unwrap())]
+            .into_iter()
+            .map(|(x, v)| (x.into(), v))
+            .collect();
 
         Entity::new(
             value.euid.into(),
@@ -109,12 +107,10 @@ pub struct Issue {
 
 impl From<Issue> for Entity {
     fn from(value: Issue) -> Entity {
-        let attrs = [
-            ("repo", format!("{}", value.repo.as_ref()).parse().unwrap()),
-        ]
-        .into_iter()
-        .map(|(x, v)| (x.into(), v))
-        .collect();
+        let attrs = [("repo", format!("{}", value.repo.as_ref()).parse().unwrap())]
+            .into_iter()
+            .map(|(x, v)| (x.into(), v))
+            .collect();
 
         Entity::new(
             value.euid.into(),
diff --git a/sql/postgres/pg_20240923__init.sql b/sql/postgres/pg_20241023__init.sql
similarity index 96%
rename from sql/postgres/pg_20240923__init.sql
rename to sql/postgres/pg_20241023__init.sql
index e03c2d67..30ecf28e 100644
--- a/sql/postgres/pg_20240923__init.sql
+++ b/sql/postgres/pg_20241023__init.sql
@@ -42,7 +42,7 @@ CREATE TABLE IF NOT EXISTS "mega_tag" (
 CREATE TABLE IF NOT EXISTS "mega_mr" (
   "id" BIGINT PRIMARY KEY,
   "mr_link" VARCHAR(40) NOT NULL,
-  "title" VARCHAR(80) NOT NULL,
+  "title" TEXT NOT NULL,
   "merge_date" TIMESTAMP,
   "status" VARCHAR(20) NOT NULL,
   "path" TEXT NOT NULL,
@@ -291,4 +291,14 @@ CREATE TABLE IF NOT EXISTS "ssh_keys" (
   "created_at" TIMESTAMP NOT NULL
 );
 CREATE INDEX "idx_user_id" ON "ssh_keys" ("user_id");
-CREATE INDEX "idx_ssh_key_finger" ON "ssh_keys" ((left(finger, 8)));
\ No newline at end of file
+CREATE INDEX "idx_ssh_key_finger" ON "ssh_keys" ((left(finger, 8)));
+
+
+CREATE TABLE IF NOT EXISTS "access_token" (
+  "id" BIGINT PRIMARY KEY,
+  "user_id" BIGINT NOT NULL,
+  "token" TEXT NOT NULL,
+  "created_at" TIMESTAMP NOT NULL
+);
+CREATE INDEX "idx_token_user_id" ON "access_token" ("user_id");
+CREATE INDEX "idx_token" ON "access_token" ((left(token, 8)));
\ No newline at end of file
diff --git a/sql/sqlite/sqlite_20240923_init.sql b/sql/sqlite/sqlite_20241023_init.sql
similarity index 96%
rename from sql/sqlite/sqlite_20240923_init.sql
rename to sql/sqlite/sqlite_20241023_init.sql
index 29fa615e..0f02858f 100644
--- a/sql/sqlite/sqlite_20240923_init.sql
+++ b/sql/sqlite/sqlite_20241023_init.sql
@@ -290,4 +290,13 @@ CREATE TABLE IF NOT EXISTS "ssh_keys" (
   "created_at" TIMESTAMP NOT NULL
 );
 CREATE INDEX "idx_user_id" ON "ssh_keys" ("user_id");
-CREATE INDEX "idx_ssh_key_finger" ON "ssh_keys" ("finger");
\ No newline at end of file
+CREATE INDEX "idx_ssh_key_finger" ON "ssh_keys" ("finger");
+
+CREATE TABLE IF NOT EXISTS "access_token" (
+  "id" BIGINT PRIMARY KEY,
+  "user_id" BIGINT NOT NULL,
+  "token" TEXT NOT NULL,
+  "created_at" TIMESTAMP NOT NULL
+);
+CREATE INDEX "idx_token_user_id" ON "access_token" ("user_id");
+CREATE INDEX "idx_token" ON "access_token" ("token");
\ No newline at end of file


Test patch: