fix: address project review findings
ci / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 48s
ci / api (push) Successful in 51s
ci / recommender (push) Canceled after 2s
ci / ts (packages + web) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (apps/web/Dockerfile, web, ) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, api, api) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, storage-agent, storage-agent) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/recommender/Dockerfile, recommender, ) (push) Canceled after 0s
ci / mobile (Metro-бандл Android) (push) Canceled after 0s
ci / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 48s
ci / api (push) Successful in 51s
ci / recommender (push) Canceled after 2s
ci / ts (packages + web) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (apps/web/Dockerfile, web, ) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, api, api) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/api/Dockerfile, storage-agent, storage-agent) (push) Canceled after 0s
ci / docker (образы собираются — их сервер собирает сам при обновлении) (services/recommender/Dockerfile, recommender, ) (push) Canceled after 0s
ci / mobile (Metro-бандл Android) (push) Canceled after 0s
Security and robustness: - storage-agent rejects an empty INTERNAL_TOKEN (config notEmpty + middleware) - api takes the client IP only from X-Real-IP (chi RealIP trusted True-Client-IP) - /readyz reports ok/fail and logs the cause; checks run in parallel with a timeout - storage-agent shuts down gracefully; shared httpx.NewServer/Serve with IdleTimeout - goose migrations take a Postgres advisory lock - recommender readyz: per-check timeout, redis socket timeouts Clients: - Android release allows cleartext HTTP for LAN servers (expo-build-properties) - checkServer times out after 10s; connect button is disabled while checking Deploy and CI: - install.sh hands cache/uploads/updates/models to the non-root service users - update.sh refuses downgrades unless PIPU_ALLOW_DOWNGRADE=1 - recommender/analyzer get only the env they need; required secrets fail fast - nginx security headers and CSP; strip True-Client-IP - dev compose binds ports to 127.0.0.1; postgres/redis images pinned - version.mjs fails on a malformed explicit tag instead of releasing 0.0.0-dev - contract check catches untracked generated files - final releases fail without a release keystore; changelog skips rc tags Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1324cad2af
commit
4fa1add80d
37 files changed
+503
-199
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import type { ConfigContext, ExpoConfig } from 'expo/config';
|
||||
|
||||
// Версию проставляет CI из git-тега (scripts/version.mjs): PIPU_VERSION=1.2.3, PIPU_VERSION_CODE=10203.
|
||||
// Версию проставляет CI из git-тега (scripts/version.mjs): PIPU_VERSION=1.2.3, PIPU_VERSION_CODE=1020399.
|
||||
const version = process.env.PIPU_VERSION ?? '0.0.0';
|
||||
const versionCode = Number(process.env.PIPU_VERSION_CODE ?? '1');
|
||||
|
||||
@@ -22,5 +22,10 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
|
||||
permissions: ['REQUEST_INSTALL_PACKAGES'],
|
||||
},
|
||||
platforms: ['android'],
|
||||
plugins: [
|
||||
// Сервер часто живёт в домашней сети без TLS (http://192.168.1.10:8080), а release-сборка
|
||||
// Android по умолчанию запрещает незашифрованный HTTP.
|
||||
['expo-build-properties', { android: { usesCleartextTraffic: true } }],
|
||||
],
|
||||
extra: { versionCode },
|
||||
});
|
||||
@@ -15,6 +15,7 @@
|
||||
"@pipu/design-tokens": "workspace:*",
|
||||
"@pipu/i18n": "workspace:*",
|
||||
"expo": "~53.0.20",
|
||||
"expo-build-properties": "~0.14.8",
|
||||
"expo-constants": "~17.1.7",
|
||||
"expo-status-bar": "~2.2.3",
|
||||
"i18next": "^25.2.1",
|
||||
|
||||
@@ -17,7 +17,10 @@ export function ConnectScreen() {
|
||||
const [address, setAddress] = useState('');
|
||||
const [state, setState] = useState<State>({ kind: 'idle' });
|
||||
|
||||
const checking = state.kind === 'checking';
|
||||
|
||||
async function onCheck() {
|
||||
if (checking) return;
|
||||
const baseUrl = normalizeServerUrl(address);
|
||||
if (!baseUrl) {
|
||||
setState({ kind: 'invalid' });
|
||||
@@ -39,6 +42,7 @@ export function ConnectScreen() {
|
||||
value={address}
|
||||
onChangeText={setAddress}
|
||||
onSubmitEditing={onCheck}
|
||||
editable={!checking}
|
||||
placeholder="https://music.home.lan"
|
||||
placeholderTextColor={colors.text3}
|
||||
autoCapitalize="none"
|
||||
@@ -62,7 +66,12 @@ export function ConnectScreen() {
|
||||
)}
|
||||
{state.kind === 'done' && state.status === 'offline' && <Status ok={false} text={t('server.offline')} />}
|
||||
|
||||
<Pressable onPress={onCheck} style={({ pressed }) => [styles.button, pressed && { opacity: 0.85 }]}>
|
||||
<Pressable
|
||||
onPress={onCheck}
|
||||
disabled={checking}
|
||||
accessibilityState={{ disabled: checking, busy: checking }}
|
||||
style={({ pressed }) => [styles.button, (pressed || checking) && { opacity: 0.6 }]}
|
||||
>
|
||||
<Text style={styles.buttonText}>{t('server.check')}</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
@@ -13,6 +13,7 @@ RUN pnpm --filter @pipu/web build
|
||||
|
||||
FROM nginx:1.28-alpine
|
||||
COPY deploy/nginx/default.conf.template /etc/nginx/templates/default.conf.template
|
||||
COPY deploy/nginx/security-headers.conf /etc/nginx/snippets/security-headers.conf
|
||||
COPY --from=build /repo/apps/web/dist /usr/share/nginx/html
|
||||
ARG VERSION=0.0.0-dev
|
||||
LABEL org.opencontainers.image.version=${VERSION}
|
||||
|
||||
Reference in new issue
Block a user